The C++ Standard Library Extensions A Tutorial and Reference

Next Page

Book Cover
The C++ Standard Library Extensions A Tutorial and Reference
By Pete Becker
...............................................
Publisher: Addison Wesley Professional
Pub Date: July 21, 2006
Print ISBN-10: 0-321-41299-0
Print ISBN-13: 978-0-321-41299-7
Pages: 624

Table of Contents | Index
Overview

"TR1 roughly doubles the size of the C++ standard library, and it introduces many new facilities and even new kinds of library components. TR1 has some classes, for example, where some nested types may or may not exist depending on the template arguments. To programmers whose experience stops with the standard library, this is strange and unfamiliar. This book is complete (it covers all TR1 facilities), it is easier to understand than TR1 itself, and it is technically accurate." --Matthew Austern,software engineer, Google

"TR1 will help make the C++ programmer more productive than ever. In this book, Pete Becker has written the ultimate reference guide to these components, what they are, how they work, and what they're used for. This book should be on the bookshelf of anyone who wants to use these standardized components to improve both their productivity as well as their coding quality." --John Maddock, consultant and programmer

The current C++ standard library extends the core C++ language with common classes and functions. In recent years, to address limitations in that library, a number of components have been developed to extend the language even further. Compiled in a comprehensive technical report (TR1), the bulk of these extensions have been approved for the next revision of the C++ standard.

In this book, Pete Becker describes in detail each component in the TR1 library, explaining new facilities for utilities, containers, call wrappers, type traits, numerics, regular expressions, and C compatibility. He draws on his own experience implementing these components to illustrate their value, clarifying the specifications when necessary and providing complete, tested code examples.

Most chapters include exercises of various degrees of difficulty to help programmers get hands-on practice with the new components. Answers to the exercises, along with all code examples, are available on the Web. Appendixes comprise a summary of headers included in or extended by the TR1 library, as well as guidelines on how to use the components safely in multithreaded applications.

The C++ Standard Library Extensions is for any programmer who wants to get a jump on the revised standard. It also makes the perfect companion to The C++ Standard Library, by Nicolai Josuttis, both books being tutorials and references essential for using C++ more effectively.

Next Page


Table of Contents

Previous Page

Book Cover
The C++ Standard Library Extensions A Tutorial and Reference
By Pete Becker
...............................................
Publisher: Addison Wesley Professional
Pub Date: July 21, 2006
Print ISBN-10: 0-321-41299-0
Print ISBN-13: 978-0-321-41299-7
Pages: 624

Table of Contents | Index

Copyright
Preface
About This Book
Acknowledgments
Further Reading
Part I: Utilities
 | Chapter 1. Tuples
 |  | Section 1.1. Header <tuple> Synopsis
 |  | Section 1.2. The tuple Class Template
 |  | Section 1.3. tuple-like Access to std::pair
 |  | Exercises
 | Chapter 2. Smart Pointers
 |  | Section 2.1. Definitions
 |  | Section 2.2. About the Examples
 |  | Section 2.3. Header <memory> Synopsis
 |  | Section 2.4. The shared_ptr Class Template
 |  | Section 2.5. The weak_ptr Class Template
 |  | Section 2.6. The enable_shared_from_this Class Template
 |  | Section 2.7. The bad_weak_ptr Class
 |  | Section 2.8. Conversions
 |  | Section 2.9. Destruction of Controlled Resources
 |  | Section 2.10. Exceptions
 |  | Section 2.11. Multithreading
 |  | Exercises
Part II: Containers
 | Chapter 3. Container Basics
 |  | Section 3.1. STL Components
 |  | Section 3.2. Containers
 |  | Further Reading
 |  | Exercises
 | Chapter 4. The array Class Template
 |  | Section 4.1. Class Template array
 |  | Section 4.2. Queries
 |  | Section 4.3. Access
 |  | Section 4.4. Modification
 |  | Section 4.5. Iteration
 |  | Section 4.6. Nested Type Names
 |  | Section 4.7. Comparisons
 |  | Section 4.8. The tuple-like Interface
 |  | Exercises
 | Chapter 5. Unordered Associative Containers
 |  | Section 5.1. Standardizing Hash Tables
 |  | Section 5.2. Hash Tables
 |  | Section 5.3. Associative Containers and Unordered Containers
 |  | Section 5.4. Requirements for Unordered Containers
 |  | Section 5.5. The Headers <unordered_map> and <unordered_-set>
 |  | Section 5.6. The Class Template hash
 |  | Section 5.7. Instantiating the Unordered Containers
 |  | Section 5.8. Constructors
 |  | Section 5.9. Container Operations
 |  | Section 5.10. Load Factors and Rehashing
 |  | Section 5.11. Tuning
 |  | Further Reading
 |  | Exercises
Part III: Call Wrappers
 | Chapter 6. Call Wrapper Basics
 |  | Section 6.1. Terminology
 |  | Section 6.2. Requirements for Call Wrapper Types
 |  | Section 6.3. Header <functional> Synopsis
 |  | Section 6.4. The result_of Class Template
 |  | Section 6.5. Interoperating with Existing Function Objects
 |  | Exercises
 | Chapter 7. The mem_fn Function Template
 |  | Exercises
 | Chapter 8. The reference_wrapper Class Template
 |  | Section 8.1. Creation
 |  | Section 8.2. Nested Types
 |  | Section 8.3. Invocation
 |  | Exercises
 | Chapter 9. The function Class Template
 |  | Section 9.1. Constructing a function Object
 |  | Section 9.2. Access
 |  | Section 9.3. Modification
 |  | Section 9.4. Comparisons
 |  | Section 9.5. Nested Types
 |  | Section 9.6. Invocation
 |  | Section 9.7. The Target Object
 |  | Exercises
 | Chapter 10. The bind Function Template
 |  | Section 10.1. Placeholders
 |  | Section 10.2. unspecified bind(.....)
 |  | Section 10.3. Extending bind
 |  | Exercises
Part IV: Type Traits
 | Chapter 11. Type Traits
 |  | Section 11.1. The Header <type_traits>
 |  | Section 11.2. Helper Types
 |  | Section 11.3. Primary Type Categories
 |  | Section 11.4. Composite Type Categories
 |  | Section 11.5. Type Properties
 |  | Section 11.6. Type Relationships
 |  | Section 11.7. Type Transformations
 |  | Section 11.8. Alignment
 |  | Further Reading
 |  | Exercises
Part V: Numerics
 | Chapter 12. Numeric Functions
 |  | Section 12.1. About the Examples
 |  | Section 12.2. Representing Floating-Point Values
 |  | Section 12.3. Managing the Floating-Point Environment
 |  | Section 12.4. Infinities, Denormals, NaNs, and Comparisons
 |  | Section 12.5. Domain and Range Errors
 |  | Section 12.6. New Overload Rules
 |  | Section 12.7. Basic Math Functions
 |  | Section 12.8. Mathematical Special Functions
 |  | Section 12.9. Functions of Complex Numbers
 |  | Further Reading
 |  | Exercises
 | Chapter 13. Random Number Generators
 |  | Getting Values
 |  | Section 13.1. Random Number Engines
 |  | Section 13.2. Engine Templates in the TR1 Library
 |  | Section 13.3. TR1 Library Class random_device
 |  | Section 13.4. Predefined Engines in the TR1 Library
 |  | Section 13.5. Random Number Distributions
 |  | Section 13.6. Discrete Distributions
 |  | Section 13.7. Continuous Distributions
 |  | Section 13.8. The variate_generator Class Template
 |  | Further Reading
 |  | Exercises
Part VI: Regular Expressions
 | Chapter 14. The <regex> Header
 |  | Further Reading
 | Chapter 15. Regular Expression Grammars
 |  | Section 15.1. Structure of Regular Expressions
 |  | Section 15.2. Grammar Features
 |  | Section 15.3. Regular Expression Details
 |  | Section 15.4. About the Exercises
 |  | Exercises
 | Chapter 16. Regular Expression Objects
 |  | Section 16.1. Definitions
 |  | Section 16.2. Header <regex> Partial Synopsis
 |  | Section 16.3. Syntax Options
 |  | Section 16.4. The basic_regex Class Template
 |  | Section 16.5. Predefined basic_regex Types
 |  | Section 16.6. Error Handling
 |  | Exercises
 | Chapter 17. Searching
 |  | Section 17.1. Header <regex> Partial Synopsis
 |  | Section 17.2. Matching Exactly
 |  | Section 17.3. Searching
 |  | Section 17.4. Search Options
 |  | Exercises
 | Chapter 18. Search Results
 |  | Section 18.1. Header <regex> Partial Synopsis
 |  | Section 18.2. The sub_match Class Template
 |  | Section 18.3. Predefined sub_match Types
 |  | Section 18.4. The match_results Class Template
 |  | Exercises
 | Chapter 19. Repetitive Searches
 |  | Section 19.1. Brute-Force Searches
 |  | Section 19.2. The regex_iterator Class Template
 |  | Section 19.3. The regex_token_iterator Class Template
 |  | Exercises
 | Chapter 20. Formatting and Text Replacement
 |  | Section 20.1. Formatting Options
 |  | Section 20.2. Formatting Text
 |  | Section 20.3. Replacing Text
 |  | Exercises
 | Chapter 21. Customizing Regular Expressions
 |  | Section 21.1. Character Traits
 |  | Section 21.2. Locales
 |  | Section 21.3. Character Matching
 |  | Section 21.4. Collating
 |  | Section 21.5. Character Classes
 |  | Section 21.6. The regex_traits Class Template
Part VII: C Compatibility
 | Chapter 22. C Compatibility
 |  | Section 22.1. Integer Types
 |  | Section 22.2. The 64-Bit Integer Types
 |  | Section 22.3. Fixed-Size Integer Types
 |  | Section 22.4. Text Conversions
 |  | Section 22.5. Format Specifiers
 |  | Section 22.6. Formatted I/O
 |  | Section 22.7. Character Classification
 |  | Section 22.8. Boolean Type
 |  | Exercises
Appendixes
 | Appendix A. Headers
 |  | Section A.1. Header <regex> Synopsis
 |  | Section A.2. Header <unordered_set> Synopsis
 |  | Section A.3. Header <unordered_map> Synopsis
 |  | Section A.4. Header <float.h> Synopsis
 |  | Section A.5. Header <math.h> Synopsis
 |  | Section A.6. Header <functional> Synopsis
 |  | Section A.7. Header <memory> Synopsis
 |  | Section A.8. Header <utility> Synopsis
 | Appendix B. Utility Headers
 |  | Section B.1. "sputil.h"
 |  | Section B.2. "mathutil.h"
 |  | Section B.3. "rgxutil.h"
 | Appendix C. Multithreading
 |  | Section C.1. Problems
 |  | Section C.2. Libraries and Multithreading
 | Bibliography
Index

Previous Page


Copyright

Many of the designations used by manufacturers and sellers to distinguish their products are claimed as trademarks. Where those designations appear in this book, and the publisher was aware of a trademark claim, the designations have been printed with initial capital letters or in all capitals.

The author and publisher have taken care in the preparation of this book, but make no expressed or implied warranty of any kind and assume no responsibility for errors or omissions. No liability is assumed for incidental or consequential damages in connection with or arising out of the use of the information or programs contained herein.

The publisher offers excellent discounts on this book when ordered in quantity for bulk purchases or special sales, which may include electronic versions and/or custom covers and content particular to your business, training goals, marketing focus, and branding interests. For more information, please contact:

U.S. Corporate and Government Sales
(800) 382-3419
corpsales@pearsontechgroup.com

For sales outside the United States please contact:

International Sales
international@pearsoned.com

Visit us on the Web: www.awprofessional.com

Library of Congress Cataloging-in-Publication Data:

Becker, Pete.
The C++ standard library extensions : a tutorial and reference / Pete Becker.
p. cm.
Includes bibliographical references and index.
ISBN 0-321-41299-0 (hardback : alk. paper)
1. C++ (Computer program language) I. Title.

QA76.73.C153B43 2006
005.13'3dc22 2006014959

Copyright © 2007 Pearson Education, Inc.

All rights reserved. Printed in the United States of America. This publication is protected by copyright, and permission must be obtained from the publisher prior to any prohibited reproduction, storage in a retrieval system, or transmission in any form or by any means, electronic, mechanical, photocopying, recording, or likewise. For information regarding permissions, write to:

Pearson Education, Inc.
Rights and Contracts Department
75 Arlington Street, Suite 300
Boston, MA 02116
Fax: (617) 848-7047

Portions of this book are derived from Dinkum Compleat Libraries Reference, Copyright © 19922006 by Dinkumware, Ltd.

Text printed in the United States on recycled paper at RR Donnelley in Crawfordsville, Indiana

First printing, July 2006

Dedication

To Angela, my college sweetheart, who, 35 years later, became my wife


Preface

He who has begun has half done. Dare to be wise; begin!

Epistles, I, ii
HORACE

This book is for C++ programmers who are frustrated with some of the limitations of the standard C++ library. The book is a tutorial and reference for the library described in the first C++ Library Technical Report, which was approved in 2006 by the International Organization for Standardization (ISO).[1] This library, which I'll call the TR1 library, isn't part of the C++ Standard. The TR is only "an informative document," but you can expect to see the library shipped with some compilers and provided as an add-on library from various library vendors. You can also expect to see many of its components incorporated into the standard library in the next C++ standard.[2]

[1] See www.iso.ch.

[2] In April, 2006, all of the TR1 library except the special math functions was added to the draft of the next C++ standard.

The TR1 library extends the standard C++ library with new facilities in several areas:

Utilities: a reference-counted smart pointer; a class template tuple that generalizes the std::pair class template to handle various numbers of arguments

Containers: sets and maps implemented with hash tables; a fixed-size array

Call wrappers: more powerful and more flexible templates that provide wrappers around functions, member functions, and other function objects, allowing them to be used more easily as arguments to algorithms

Type traits: a set of templates that extract properties of types or modify types at compile time, simplifying template metaprogramming

Numerics: a rich set of random number generators; advanced mathematical special functions; numeric facilities like those added to the C language in 1999

Regular expressions: classes and functions to describe and search for patterns in text

C compatibility: types, functions, and macros like those added to the C language in 1995 and 1999

Formal work on the TR1 library began in 2001, when the C++ Standards Committee, through its Library Working Group, asked for proposals. Most of the proposals that made it into the library came from members of Boost,[3] an organization set up in 1998 by Standards Committee members who were looking for a way to develop new libraries without the constraints imposed by the process of standardization. The added flexibility from working outside that formal process made it possible to develop the pieces of the Boost libraries on independent schedules far more rapidly than is possible within a standards committee. Boost is a thriving organization, and its library has many useful things that are not in the TR1 library.

[3] See www.boost.org

The Standards Committee meets twice a year. From 2001 to 2005, the Library Working Group spent most of its time at those meetings, as well as a great deal of e-mail time between meetings, working on the TR1 library. During that time, the working group refined the proposals it had received: simplifying where appropriate, rewriting both for clarity and for the formalism required in an ISO standard, and unifying the presentation of the pieces of the library.

Toward the end of 2002, the company I worked for, Dinkumware, Ltd., began implementing the TR1 library. Dinkumware sells standard libraries for C, C++, and Java, so this was a natural step for us. Our work also helped improve the Technical Report, as we found things that were vaguely described, overspecified, or simply missing.[4] Dinkumware has a complete implementation of the TR1 library, and I've used it in all the examples in this book.

[4] That's not a criticism of the work done by the folks at Boost; they began by writing documentation for their library contributions, then turned that documentation into preliminary specifications for their proposals. That second step is difficult, and it rarely goes smoothly.


About This Book

This book is divided into seven parts, each one covering one area of the new facilities. Each part begins with an overview of those facilities. The overview usually includes some remarks about their history and, in some cases, reasons why some obvious features are not in the TR1 library.

Each part has a synopsis of the header or headers that define the library components discussed in that part. The synopsis is not, in general, compilable code but instead presents an overview of the components that the header defines, listing all the templates, classes, non-member functions, objects, constants, and so on, that are defined in that header. Each of those things is defined in more detail later. However, even the more detailed definitions often are not compilable code. Many of the details are implementation dependent, and nothing would be gained by slogging through them.

Each synopsis is highlighted in gray. Most are followed by the formal requirements from the C++ standard. These formal requirements are indented. Informal discussions are not indented. For example:

class C
{
};

This text gives the formal requirements for the class C. It is usually dense and technical. While its words are definitive, they are often hard to read. Text that is not indented is informal. It provides a more approachable, but sometimes less precise, description.

Most chapters end with a set of exercises that review the concepts covered in the chapter. Some exercises are easy, and some are deliberately difficult. Don't worry if you can't solve all of them.

To avoid confusion, I often use formal language to identify the things that I'm talking about. It's far too common for discussions to bog down because the participants don't know whether they're talking about templates, classes, or objects. For example, the TR1 library has a template named function that holds function objects. Rather than make you guess whether the word function refers to that template or to an object created from that template, I've tried to consistently use such phrases as "the class template function," "specialization of the class template function," and "object of type function<T>."

All the code examples are complete: They will compile with a suitable compiler and library. Examples that have a main function will also link and run. The examples have been tested with Microsoft's C/C++ compiler,[5] version 7.1; and with the GNU Project's gcc compiler,[6] version 3.4.3, using the Dinkum TR1 Library Version 1.0 from Dinkumware, Ltd.[7] Source code for the examples can be downloaded from my Web site.[8]

[5] www.microsoft.com

[6] www.gnu.org

[7] www.dinkumware.com

[8] www.petebecker.com/tr1book

ISO, Conformance, and the TR1 library

The ISO C++ standard is a specification for the C++ programming language, defining what is and is not a valid C++ program and for valid programs telling you, within certain limits, what that program should do. The TR1 library is not part of the C++ standard, although most of the library will almost certainly become part of the standard in its next revision, around 2010. In the meantime, compilers that conform to the C++ standard do not need to include the TR1 library.[9]

[9] Technically, they should not include it, because it adds names that could conflict with names that are already in use in valid programs. In practice, this won't be a significant problem. The TR1 library puts its names in the namespace TR1, which is nested in the namespace std. As a result, the directive using namespace std; will hoist the name tr1 into the global namespace, possibly clashing with existing code that uses that name. In addition, code that defines macros with the same names as any of the contents of the TR1 library will run into problems. Of course, we all write macro names in capitals, so this shouldn't cause any problems.

The standard defines and uses several technical terms to talk about valid and invalid programs and about the meaning of a valid program. The Library Technical Report uses the same terminology. Programmers are often confused about the meanings of these terms.[10] They're not particularly complicated, though, so if you're interested, read on.

[10] In fact, many of the original proposals that turned into the TR1 library misused them; the Library Working Group tried to fix these misuses, but a few mistakes may still be left in the Technical Report.

A diagnostic message is any compiler[11] output message that results from a violation of the rules that the standard sets out. The compiler is allowed to give other messages as well, but the compiler's documentation is required to tell you which messages are diagnostic messages.

[11] The standard uses the term implementation to refer to the compiler, linker, and whatever else is needed to convert source code into an executable program. I'll use the conventional shorthand term compiler to mean the same thing.

When the standard says that some code results in undefined behavior, it means that the standard does not impose any requirements on what a compiler does when compiling a program that uses that code. Unfortunately, code whose behavior is undefined often results in a program that does exactly what you thought it would do but only until you change to a different compiler. This makes debugging very difficult, so it's best to avoid writing code whose behavior is undefined.

A diagnosable rule is any standard rule that doesn't say "no diagnostic required" and that doesn't result in undefined behavior. If your code violates a rule that doesn't require a diagnostic, the standard allows your compiler to do anything at all; you've done something that the C++ standard does not recognize, so you're on your own. If your code violates a diagnosable rule, the compiler must issue at least one diagnostic message.[12] That doesn't mean that the compiler must report every diagnosable error; nor does it mean that it cannot give diagnostic messages when compiling a program without diagnosable errors. Technically, a compiler that reports "an error occurred" every time you compile code meets the requirements of the C++ standard. Of course, nobody would use a compiler that did that, if they could avoid it.

[12] You'll often hear that the compiler should refuse to compile code that violates a diagnosable rule. That's wrong. The only requirement is that the compiler must issue a diagnostic. That's the hook for language extensions: Once it has issued a diagnostic, the compiler can do whatever the compiler writer thinks is appropriate.

The One Definition Rule requires that definitions of things that ought to be the same must in fact be the same. For example, if you define a struct named data with two members of type int in one source file and you define a struct named data with three members of type double in another source file, you've violated the One Definition Rule. Such violations don't require a diagnostic. They can lead to very mysterious problems.

A well-formed program is one that doesn't violate any diagnosable rule and doesn't violate the One Definition Rule. An ill-formed program is one that isn't well formed.

Because they run on systems with finite amounts of storage, compilers have resource limits, which prevent them from compiling programs that are too complicated. The C++ standard recommends some minimum values for such things as the maximum nesting level of compound statements (256), the maximum number of case labels for a switch statement (16, 384), and the maximum number of nested template instantiations (17). Compilers are required to document these limits when they are known. These days, however, compilers are getting away from fixed-size tables, instead allocating their internal data structures dynamically as needed; this means that the limits change, depending on what else is being done in the program. What this comes down to is that you can't assume that a well-formed program that compiles with one compiler will also compile with another compiler, including a different version of the "same" compiler. The program can run up against more restrictive resource limits when you change compilers.

A conforming implementation is a compiler that correctly compiles well-formed programs that do not exceed its resource limits. The resulting executable must, of course, do what the C++ standard says it should do. That's not quite as clear-cut as it seems, though; in many cases, the standard allows executables compiled from the same source code to behave differently.

The C++ standard sometimes says that code has unspecified behavior. Usually, this means that it could do several reasonable things, and the C++ standard doesn't require any particular one of them. For example, the order of evaluation of arguments to a function is unspecified. This means that for code like f(g(), h()), the compiler is free to call the function g before it calls the function h or to call h before it calls g. If your code assumes that g will be called before h, you may be in for a surprise when you change compilers or when you change the optimization settings for the compiler you've been using.

The standard also says that some code has implementation-defined behavior. Like code with unspecified behavior, there are usually several reasonable alternatives, and the standard doesn't require any particular one. It does, however, require the implementation to document what it does. For example, the basic type char can be either signed or unsigned, and the compiler's documentation must tell you which one you get.

Finally, the normative text in the standard is what you look to for the syntactic and semantic requirements. Text enclosed by "[Note: ... -- end note]", examples, text in footnotes, and chapter and section titles are non-normative; they help you find your way through the standard, but they do not impose requirements. For example, if a footnote and a piece of ordinary text conflict, the ordinary text wins.


Acknowledgments

Thanks to all the members of the Library Working Group for their contributions to the TR1 library. Special thanks to Matt Austern, who, as chair of the Library Working Group, kept us focused and refereed the sometimes heated discussions, and to the people who wrote the seminal papers for the TR1 library: Matt Austern, unordered containers; Walter Brown, mathematical special functions; Greg Colvin, shared_ptr; Beman Dawes, shared_ptr; Peter Dimov, reference_wrapper, shared_ptr, mem_fn, and bind; Doug Gregor, reference_wrapper, function and bind; Jaakko Järvi, tuple and bind; John Maddock, type traits and regular expressions; Jens Maurer, random number generators; Alisdair Meredith, array; P.J. Plauger, C compatibility; and Gary Powell, bind.

Thanks to Bjarne Stroustrup for inventing this wonderful language and for referring me to the folks at Addison-Wesley Publishing. Thanks to everyone at Addison-Wesley Publishing who made this book possible: Peter Gordon, Kim Boedigheimer, Elizabeth Ryan, Evelyn Pyle, John Fuller, Chanda Leary-Coutu, and Marie McKinley.

Thanks to Doug Gregor, John Maddock, Matt Austern, and Marc Paterno for reviewing a draft of this book. Their comments were invariably insightful and helpful.

Thanks to the folks who run Dinkumware, Ltd.P.J. Plauger and Tana Plaugerfor encouraging me to write this book and for allowing me the time to do it.

Thanks to my wife, Angela Pao, who, among countless other things, reminded me from time to time to take a break.


Further Reading

  • ISO/IEC Standard 14882:2003, Programming LanguagesC++ [Int03a] is the definitive technical reference for the C++ language and the standard C++ library.

  • ISO/IEC Standard 9899:1990, Programming LanguagesC [Int90] was the definitive technical reference for the C language and the standard C library when the C++ standard was written. Significant parts of the C++ language and standard C++ library are incorporated by reference from this document.

  • Amendment 1 to ISO/IEC Standard 9899:1990, Programming LanguagesC [Int95] provides greatly improved support for internationalization in C.

  • ISO/IEC Standard 9899:1999, Programming LanguagesC [Int99] is the definitive technical reference for the C language and the standard C library, providing, among other things, much more rigorously defined support for floating-point math, both in the language and in the library. The TR1 library incorporates all the library changes that C99 made to the standard C library.

  • The C++ Standard Library [Jos99] is a comprehensive, readable reference and tutorial for the standard C++ library.


Part I: Utilities

    Chapter 1. Tuples

    Chapter 2. Smart Pointers


Chapter 1. Tuples

You cannot conceive of the many without the one.

Parmenides
PLATO

The class template tuple is a generalization of the standard C++ library class template pair. The pair template takes two type arguments; objects of type pair<T1, T2> hold two elements: one of type T1 and one of type T2. The tuple template extends this by taking an arbitrary number of type arguments. Objects of type tuple<T1, T2, ..., T N> hold N elements of types T1, T2, ..., T N, respectively.[1]

[1] Each library implementation is allowed to put an upper limit on the value of N. The Library Technical Report recommends that this upper limit be at least 10.

Example 1.1. Tuple Declarations (tuples/typedefs.cpp)

#include <tuple>
using std::tr1::tuple;

tuple<> none;                      // holds no elements
tuple<int> one;                    // holds one element, of type int

int i; double d;
tuple<int&, const double&>
    two(i,d);                      // holds two elements, one of
                                   // type reference to int and one
                                   // of type reference to const double
tuple<int, int, int, int, int,
   int, int, int, int, int> ten ;  // holds ten elements, all of type int

You can create tuple objects through each tuple type's constructors. In addition, two function templatesmake_tuple and tiereturn tuple objects whose types are based on the arguments to the functions. These techniques for creating tuple objects are covered in Section 1.2.1.

The function template get returns a reference to an element of a tuple object. The result can be used to examine the value of the element and to modify an element of a non-const tuple object. The values of elements can also be changed by assigning one tuple object to another. These access mechanisms are covered in Section 1.2.2.

You can ask about the size of a specialization of tuple and the type of each of its elements through the class templates tuple_size and tuple_element. These templates are covered in Section 1.2.3.

You can compare two tuple objects of the same size for equality and for relative order. See Section 1.2.4.


Section 1.1. Header <tuple> Synopsis

1.1. Header <tuple> Synopsis

namespace std {
 namespace tr1 {
    // TUPLE CLASS TEMPLATES
template<class T1, class T2, ..., class TN>
  class tuple;
template<class Tuple> struct tuple_size;
template<int Idx, class Tuple> struct tuple_element;

    // TUPLE FUNCTION TEMPLATES
template<int Idx, class T1, class T2, ..., class TN>
  RI get(tuple<T1, T2, ..., TN>&);
template<int Idx, class T1, class T2, ..., class TN>
  RI get(const tuple<T1, T2, ..., TN>&);
template<class T1, class T2, ..., class TN>
  tuple<V1, V2, ..., VN>
  make_tuple(const T1 &, const T2 &, ..., const TN &);
template<class T1, class T2, ..., class TN>
  tuple<T1&, T2 &, ..., TN&>
  tie(T1 &, T2 &, ..., TN &);

     // CONSTANTS
const unspecified ignore;

    // COMPARISON OPERATORS
template<class T1, class T2, ..., class TN,
    class U1, class U2, ..., class UN>
  bool operator==(const tuple<T1, T2, ..., TN>&,
    const tuple<U1, U2, ..., UN>&);
template<class T1, class T2, ..., class TN,
    class U1, class U2, ..., class UN>
  bool operator!=(const  tuple<T1, T2, ..., TN>&,
    const tuple<U1, U2, ..., UN>&);
template<class T1, class T2, ..., class TN,
    class U1, class U2, ..., class UN>
  bool operator<(const  tuple<T1, T2, ..., TN>&,
    const tuple<U1, U2, ..., UN>&);
template<class T1, class T2, ..., class TN,
    class U1, class U2, ..., class UN>
  bool operator<=(const tuple<T1, T2, ..., TN>&,
    const tuple<U1, U2, ..., UN>&);
template<class T1, class T2, ..., class TN,
    class U1, class U2, ..., class UN>
  bool operator>(const tuple<T1, T2, ...,  TN>&,
    const tuple<U1, U2, ..., UN>&);
template<class T1, class T2, ..., class TN,
    class U1, class U2, ..., class UN>
  bool operator> =(const tuple<T1, T2, ..., TN>&,
    const tuple<U1, U2, ..., UN>&);
} }


Section 1.2. The tuple Class Template

1.2. The tuple Class Template

template<class T1, class T2, ..., class TN>
class tuple {
public:
  // CONSTRUCTORS
  tuple ();
  explicit tuple(P1, P2, ..., PN);             // when N> 0
  tuple(const tuple &);
  template<class U1, class U2, ..., class UN>
    tuple(const  tuple<U1, U2, ..., UN>&);
  template<class U1, class   U2>
    tuple(const  pair <U1, U2>&);             // when N == 2

  // ASSIGNMENT OPERATORS
  tuple & operator=(const tuple &);
  template<class U1, class U2, ..., class UN>
    tuple & operator = (const tuple<U1, U2, ..., UN>&);
  template< class U1, class U2>
    tuple & operator = (const pair <U1, U2>&);  // when N == 2
  };

1.2.1. Creating a tuple Object

You can create a tuple object in several ways. If all the element types have default constructors, a tuple holding those element types also has a default constructor; it constructs a tuple object with all its elements constructed with their respective default constructors. In addition, each tuple type that holds one or more elements has a constructor that takes as many arguments as the type has elements; it constructs each stored element from the corresponding argument. Obviously, each argument type must be convertible to the appropriate element type. Finally, a tuple object can be constructed by copying another tuple object with the same number of elements and, when the tuple object that's being constructed holds two elements, by copying a pair object.

Example 1.2. Tuple Constructors (tuples/ctors.cpp)

#include <utility>
#include <tuple>
using std::tr1::tuple; using std::pair;

class C {
public:
  C (): val (0) {}
  C(int i) : val (i) {}
private :
  int val;
};

tuple<> t0;                   // default constructor
tuple<int>t1;                 // default constructor; element
                              // not initialized
tuple<int> t2  (3);           // element initialized to 3
tuple<C> t3;                  // element initialized to C()
tuple<C> t4(C   (1));         // element initialized to C(1)
tuple<C, C> t5 (1,2);         // first element initialized to C(1)
                              // second element initialized to C(2)
tuple<double>  t6(t2);        // element initialized to 3.0
pair <int, int> p0 (3, 4);    // first element initialized to 3
                              // second element initialized to 4
tuple<C, C> t7(p0);           // first element initialized to C(3)
                              // second element initialized to C(4)

Sometimes, it's inconvenient to have to list the type arguments for tuple. When you know the values that you want a tuple object to hold, you can use the function make_tuple to create a tuple object that holds copies of its arguments.

Example 1.3. Function Template maketuple (tuples/maketuple.cpp)

#include <tuple>
#include <typeinfo>
#include <iostream>
using std::tr1::tuple; using std::tr1::make_tuple;

template <class T> void show_type (T)
    {
    std::cout << typeid (T). name() << "\n\n";
    }

int main()
    {
    int i = 3;
    int & j = i;
    show_type (make_tuple ());            // returns tuple<>
    show_type (make_tuple (1,   3.14));   // returns tuple<int,double>
    show_type (make_tuple (i, j));        // returns tuple<int,int>
    return 0;
    }

If you ran this example and managed to wade through the lengthy names of the tuple types that your compiler generated, you probably noticed that the last call to make_tuple returns an object of type tuple<int, int>, even though the second argument to make_tuple is a reference to int. The function template make_tuple doesn't distinguish between objects and references to objects. Both result in an element with the type of the object.

To create a tuple object that holds references, use the TR1 library function templates ref and cref, defined in the header <functional>. These functions have other uses that we discuss in detail later (see Section 8.1). For now, ref is a wrapper that tells make_tuple that the corresponding element type is a reference to the type of the argument to ref. Similarly, cref tells make_tuple to create an element that's a reference to a const value type.

Example 1.4. Use of ref and cref (tuples/refcref.cpp)

#include <tuple>
#include <functional>                    // for ref, cref
using std::tr1::make_tuple;
using std::tr1::ref; using std::tr1::cref;
void test ()
    {
    int i = 17;
    int j = 3;
    make_tuple (ref (i), cref (j));     // returns tuple<int&, const int&>
                                        // first element is reference to i
                                        // second element is reference to j
    }

Sometimes you'll want to create a tuple object that holds only references to objects. As we just saw, you can use ref to do this, but that can turn into a lot of typing. The function template tie is a convenient way of creating a tuple object that holds references to its arguments. Passing the value ignore as an argument tells tie that the tuple object it returns should ignore assignments to the element that corresponds to that argument.

Example 1.5. Function Template tie (tuples/tie.cpp)

#include <tuple>
#include <iostream>
using std::tr1::make_tuple; using std::tr1::tie;
using std::tr1::ignore;

int i = 1;
int j = 2;
int k = 3;

void  show ()
  {
  std::cout << i << ' ' << j << ' ' << k << '\n';
  }

int main()
  {
  show ();                      // 1 2 3
  tie (i, ignore, k) =
    make_tuple (5, 6, 7);
  show ();                      // 5 2 7
  return 0;
  }

1.2.2. Access

You can change the values in a tuple object by assigning the value of another tuple object to it. The two objects must hold the same number of elements, and the type of each of the elements in the source object must be convertible to the type of the corresponding element in the target object.

You can also change the values of a tuple object that holds two elements by assigning from a pair object.

Example 1.6. Assigning tuple Objects (tuples/assign.cpp)

#include <utility>
#include <iostream>
#include <tuple>
using std::tr1::tuple; using std::tr1::get;
using std::cout; using std::make_pair;

void show(int i, int j, const   tuple<int, int &, int>& t)
  {
  cout << i <<  '  '  << j << ":"
       << get <0>(t)   << ' '
       << get <1>(t)   << ' '
       << get <2>(t)   << '\n';
  }

void show(const tuple<int,int>& t)
  {
  cout << get <0>(t)   << ' '
       << get <1>(t)   << ' \n ' ;
  }

int main()
  {
  int i = 1, j = 2;
  tuple<int, int &, int> t0(i, j,   3);
  tuple<int, double,char> t1    (4, 5.1, ' \6 ' );
  show(i,j,t0 );                      // 1 2: 1 2 3
  t0 = t1;
  show(i,j,t0 );                      // 1 5: 4 5 6
  tuple<int,int> t2 (1,2);
  show(t2);                           // 1 2
  t2 = make_pair (3,4);
  show(t2);                           // 3 4
  return 0;
  }

The function template get takes a tuple object and returns a reference to the value of one of its elements or, when the element is itself a reference, a copy of that reference. The syntax for this function call looks a little odd. To get the nth element, you pass the value of n as a template argument.[2]

[2] Note that n is zero based: For the first element, n == 0. This numbering is different from the numbering that we use for the template's type arguments, which starts at 1. If we tried to give the type arguments names that started with 0, we'd end up with the last argument being named something like TN-1, which isn't a valid identifier.

Example 1.7. Function Template get (tuples/get.cpp)

#include <tuple>
#include <iostream>
using std::tr1::tuple; using std::tr1::get;
using std::cout;

int main()
  {
  tuple<int,int> t0(1, 2);
  cout << get<0>(t0) << ' ' << get <1>(t0) << '\n';     // 1 2
  return 0;
  }

Since it returns a reference to an element of a tuple, you can use get to change the value of that element or, when the element is itself a reference, to change the value of the object that it refers to.

Example 1.8. Modifying with get (tuples/getmod.cpp)

#include <tuple>
#include <iostream>
using std::tr1::tuple; using std::tr1::get;
using std::cout;

void show (int i, int j, const tuple<int, int&, int> t)
  {
  cout << i << ' '  << j << ": "
       << get<0>(t) << ' '
       << get<1>(t) << ' '
       << get<2>(t) << '\n';
  }

int main()
  {
  int i = 1, j = 2;
  tuple<int, int&, int> t0(i, j, 3);
  show(i, j, t0);               // 1 2: 1 2 3
  get<0>(t0) = 4;               // set first element to 4
  get<1>(t0) = 5.1;             // set object referred to by
                                // second element to 5
  get<2>(t0) = '\6';            // set third element to 6
  show (i, j, t0);              // 1 5: 4 5 6
  return 0;
  }

1.2.3. Type Queries

If you need to know how many elements a tuple type holds, you can use the class template tuple_size.

template<class Tuple> struct tuple_size
  {
  static const unsigned value = ...;
  };

When this template is instantiated with a tuple type, its nested member value holds the number of elements in the tuple type.

Example 1.9. Class Template tuple_size (tuples/tuplesize.cpp)

#include <tuple>
#include <iostream>
using std::tr1::tuple; using std::tr1::tuple_size;
using std::cout;

typedef tuple<> tuple0;
typedef tuple<int> tuple1;
typedef tuple<int&,double&> tuple2;
typedef tuple<int,int,int,int,int> tuple5;

int main()
  {
  cout << tuple_size <tuple0>::value << '\n';    // 0
  cout << tuple_size <tuple1>::value << '\n';    // 1
  cout << tuple_size <tuple2>::value << '\n';    // 2
  cout << tuple_size <tuple5>::value << '\n';    // 5
  return 0;
  }

To determine the type of an element, use the class template tuple_-element.

template<int Idx, class Tuple> struct tuple_element
  {
  typedef ... type;
  };

When this template is instantiated with the value of the index of the desired element and a tuple type, its nested member type names the type of the element.

Example 1.10. Class Template tuple_element (tuples/tupleelt.cpp)

#include <tuple>
#include <iostream>
#include <typeinfo>
using std::tr1::tuple; using std::tr1::tuple_element;
using std::cout;

typedef tuple<int> tuple1;
typedef tuple<int&,double&> tuple2;

template<class Ty>
void show_type ()
  {
  cout << typeid (Ty).name() << '\n';
  }

int main()
  {
  show_type<tuple_element <0, tuple1>::type>(); // int
  show_type<tuple_element <0, tuple2>::type>(); // int
  show_type<tuple_element <1, tuple2>::type>(); // double
  return 0;
  }

1.2.4. Comparison

Two tuple objects can be compared if they have the same number of elements and the corresponding individual elements can be compared. The usual six comparison operators ==, !=, <, <=, >, >= are provided. All the comparisons are short circuited: That is, comparisons are made element by element until the result is known, and no further comparisons are made. For example, when comparing two objects of type tuple<int, int> for equality, when the first object holds the values 0 and 2 and the second object holds the values 1 and 3, only the values of the first elements are compared; the equality test fails, and there is no need to compare the values of the second elements.

Comparisons for equality (t0 == t1) apply the operator == to the corresponding elements. Comparisons for inequality (t0 != t1) apply operator == to the tuples and negate the result.

The operator < is more complicated. The rule is that the comparison is a lexicographical comparison; that is, the leftmost pair of corresponding elements that are not equal determines the result.[3] However, to determine the order of two tuples, the elements are compared using only operator < on the individual elements. Two elements are equal if neither one is less than the other. To see this better, let's compare these two objects by hand:

[3] This is what you do when you alphabetize a list of words; andy comes before ants because d comes before t.

tuple<int, double, int> first (0, 2.0, 1);
tuple<long, float, int> second (0, 1.0, 2);

To decide whether first < second, we begin by comparing the first element of first and the first element of second:

get<0>(first) < get<0>(second) // false: both elements are 0

Since the result of the comparison was false, we look at the opposite comparison:

get<0>(second) < get<0>(first) // also false: both elements are 0

Now we know that the first elements of the two tuples are equal. We don't yet know whether first is less than second, so we move to the next element:

get<1>(first) < get<1>(second) // false: 2.0 is not less than 1.0f

Since the result of the comparison was false, we again look at the opposite comparison:

get<1>(second) < get<1>(first) // true: 1.0f < 2.0

We end the comparison here because we found the leftmost pair of elements that are not equal, and that pair determines the order of the two tuples. Since get<1>(second) is less than get<1>(first), the tuple second is less than the tuple first, and the result of the comparison first < second is false.

The other three comparison operators are defined in terms of operator <. The expression first > second is equivalent to second < first; first <= second is equivalent to !(second < first); and first >= second is equivalent to !(first < second).

To see this in action, compile and run the following example.

Example 1.11. Comparing tuple Objects (tuples/compare.cpp)

#include <iostream>
#include <iomanip>
#include <tuple>
using std::tr1::tuple;
using std::cout; using std::boolalpha;

class C {
public:
  C(int i) : val (i) {}
  int value() const {return val;}
private:
  int val;
};

bool operator==(const C& left, const C& right)
  {
  bool res = left.value() == right.value();
  cout << "  " << left.value()
       << " == " << right.value();
  cout << " is " << res << '\n';
  return res;
  }

bool operator <(const C& left, const C& right)
  {
  bool res = left.value() < right.value();
  cout << "  " << left.value()
       << " < " << right.value();
  cout << " is " << res << '\n';
  return res;
  }

#define TEST (expr)         \
  cout << #expr << '\n';    \
  cout << "    result is " << (expr) << '\n'

typedef tuple<C&,C&,C&> tuple1;
int main()
  {
  C a = 1;
  C b = 2;
  C c = 3;
  C d = 1;
  C e = 4;
  C f = 3;
  cout << boolalpha;                  // set alphabetic form for bool
  tuple1 t0(a, b, c);
  tuple1 t1(d, e, f);
  TEST (t0 == t1 );                   // a == d is true, b == e is false,
                                      // result is false
  TEST (t0 != t1);                    // t0 == t1 is false, result is true
  TEST (t0 < t1);                     // a  < d is false,
                                         // d  < a is false and b  < e is true,
                                         // result is true
  TEST (t1 < = t0);                   // t0  < t1 is true, result is false
  TEST (t1 > t0);                     // t0  < t1 is true, resul        t is true
  TEST (t0 > = t1);                   // t0  < t1 is true, result is false
  return 0;
  }


Section 1.3. tuple-like Access to std::pair

1.3. tuple-like Access to std::pair

For uniformity, the TR1 library adds a pair of get function templates: one taking a reference to a pair object, and the other taking a reference to a const pair object. Both return a reference to the element at the position specified by the explicit template argument. The library also adds specializations of the tuple_element and tuple_size templates, which give the element types and element count for specializations of pair.

1.3.1. Header <utility> Synopsis

namespace std {
template<class T1, class T2>
  struct pair;
  namespace tr1 {
    // PAIR FUNCTION TEMPLATES
template<int Idx, class T1, class T2>
  RI get(pair <T1, T2>&);
template<int Idx, class T1, class T2>
  RI get(const pair <T1, T2>&);

    // PAIR CLASS TEMPLATES
template<class T1, class T2>
  struct tuple_size<pair<T1, T2> >;
template<class T1, class T2>
  struct tuple_element<0, pair<T1, T2> >;
template<class T1, class T2>
  struct tuple_element<1, pair<T1, T2> >;
} }

1.3.2. Details

The overloaded get versions that take an object of type pair<T1, T2> return references to the designated element. For a pair object pr, the call get<0>(pr) returns a reference to pr.first, and the call get<1>(pr) returns a reference to pr.second.

Since a pair object always holds two elements, the specialization of tuple_size for pair types always holds a nested value of 2.

template<class T1, class T2>
struct tuple_size<pair<T1, T2> >
  {
  static const unsigned value = 2;
  };

The specialization of tuple_element for pair acts just like the version of tuple_element for tuple. The value of the template argument Idx can be only 0 or 1.

template< class T1, class T2>
struct tuple_element<0, pair<T1, T2> >
  {
  typedef T1 type;
  };
template<class T1, class T2>
  struct tuple_element<1, pair <T1, T2> >
  {
  typedef T2 type;
  };

Example 1.12. tuple-like Interface to pair (tuples/pair.cpp)

#include <iostream>
#include <typeinfo>
#include <utility>
using std::pair; using std::make_pair;
using std::tr1::get; using std::tr1::tuple_element;
using std::tr1::tuple_size;
using std::cout;

template<class  Ty>
void show (const Ty& pr)
  {
  cout << "size:   " << tuple_size<Ty>::value << '\n';
  cout << "first type:  "
    << typeid (tuple_element<0, Ty>::type).name() << '\n';
  cout << "second type: "
    << typeid (tuple_element<1, Ty>::type).name() << '\n';
  cout << "first:  " <<get<0>(pr) << '\n';
  cout << "second: " <<get<1>(pr) << '\n' << '\n';
  }

int main()
  {
  show(make_pair (1,2));
  show(make_pair (3.0,1.1 f));
  return 0;
  }


Exercises

Exercise 1

One of the biggest difficulties in writing code that uses heavily templatized types, such as tuple, is deciphering the messages that your compiler and your library implementation produce when your code has an error.

For each of the following errors, write a simple test case containing the error, and try to compile it. In the error messages, look for the key words that relate to the error in the code. This will make developing code that uses tuple much easier.

  1. Attempting default construction of a tuple object when one or more of the element types does not have a default constructor

  2. Attempting copy construction of a tuple<T> object from a tuple<U> object when objects of type U are not convertible to type T

  3. Attempting assignment of a tuple<T> object from a tuple<U> object when objects of type U are not convertible to type T

  4. Attempting copy construction or assignment to a tuple object from a tuple object with a different number of elements

  5. Attempting to call get with an index that is greater than the number of elements in the tuple argument

Exercise 2

Write and compile a source file that defines the following types:

  1. tuple0, a type that is a synonym for a tuple specialization that holds no elements

  2. tuple1, a type that is a synonym for a tuple specialization that holds one element, of type long double

  3. tuple2, a type that is a synonym for a tuple specialization that holds two elements: the first of type long double and the second of type reference to unsigned long

  4. tuple7, a type that is a synonym for a tuple specialization that holds elements of the following types: char, short, int, long, float, double, long double

Exercise 3

Write a program that creates objects of type tuple<unsigned char, unsigned char, unsigned char>[4] in three ways and displays their stored values. Do this in two steps:

[4] A tuple holding int values is more natural, but technically, you can't copy or display uninitialized values of integral types other than the three forms of char in portable code. Although this is rarely a problem in practice, the behavior of a program that does this is not defined by the C++ standard.

  1. Write a function named show that takes an argument of type const tuple<unsigned char, unsigned char, unsigned char>& and displays the three values that it holds. Use the templates get<0>, get<1>, and get<2> to get the values.

  2. In the main function, create the objects and pass them to show.

Exercise 4

Write a program that creates three auto variables of type int, all initialized to 0, and an auto object of type tuple<int&, int&, int&> that holds references to the three auto variables. Use the tuple object to show the values of the auto variables. Now change the values of the auto variables.

  1. Write three statements that use the tuple object to change the values of the three auto variables one at a time to 1, 2, and 3. Use the tuple object to show the new values.

  2. Write a single statement that uses the tuple object to change the values of the three auto variables to 4, 5, and 6. Show the new values of the auto variables. Hint: Use make_tuple.

  3. Write a single statement that creates a temporary object of type tuple<int, int, int> holding the values 7, 8, and 9 and assigns the values held in that tuple object to the three auto variables. Show the new values of the auto variables. Hint: Use a temporary object of type tuple<int&, int&, int&> to change the values of the three auto variables.

  4. Write a single statement that creates a temporary object of type tuple<int, int, int> holding the values 10, 11, and 12 and assigns the first and third values held in that tuple object to the first and third auto variables. Show the new values of the auto variables. Hint: Use tie.

Exercise 5

Write a program that shows the properties of several tuple instances.

  1. Write a function template that can be called with a tuple object holding an arbitrary number of elements that shows how many elements the object holds. Use this function to show the sizes of several tuple types. Hint: To write a function template that takes only tuple instances of various sizes, you'd have to write a separate function for each possible size. That's tedious and not particularly interesting. Instead, write a function template that takes an argument of any type and assumes that the type of the argument is, in fact, a tuple instance.

  2. Write a function template that can be called with a tuple object holding two elements that shows the types of the elements, using typeid::name. Use this function to show the types of the elements in several tuple instances.

Exercise 6

Consider the following objects:

tuple<int, int, int> t0 (1, 2, 3);
tuple<double, double, double> t1 (1.0, 2.0, 3.0);
tuple<double, double, double> t2 (1.0, 2.1, 2.9);

  1. What should the result of each of the following comparisons be?

    1. t0 == t1

    2. t0 == t2

    3. t0 < t1

    4. t0 < t2

  2. Now write a program to create these three objects, perform each of the preceding comparisons, and report the result. Compile and run the program.

Exercise 7

Some math libraries implement the sin and cos functions by calling a single function that computes both values, then picking the appropriate result.

  1. Write the prototype for that single function, with the name sincos, taking one argument of type double and returning the two double values in a tuple object.

  2. Write a function named split that takes one argument of type double and two arguments of type double&, calls sincos, and copies the two result values into its two reference arguments, without using any tuple variables.

  3. Assume that the function sincos has three overloaded versions, one taking an argument of type float and returning values of type float, one taking an argument of type double and returning values of type double, and one taking an argument of type long double and returning values of type long double. Rewrite the function split as a template that calls the appropriate version of sincos, depending on the type of its arguments.

Exercise 8

Suppose that we want to calculate the distance from the origin to a point in one-, two-, or three-dimensional space, with the location of the point held in an appropriately sized tuple object.

  1. Write a function named distance1[5] that takes an object of type tuple<double> and returns the distance from the origin to the point in one-dimensional space.

    [5] This function could be called distance and suitably overloaded, but that would get confusing when we start talking about a template with that name later on.

  2. Write a function named distance2 that takes an object of type tuple <double, double> and returns the distance from the origin to the point in two-dimensional space.

  3. Write a function named distance3 that takes an object of type tuple<double, double, double> and returns the distance from the origin to the point in three-dimensional space.

  4. Test the three distance functions with the following values:

    1. make_tuple(1.0)

    2. make_tuple(3.0, 4.0)

    3. make_tuple(3.5, 4.5, 5.5)

  5. What happens if you call any of the distance functions with a tuple object that holds no elements?

Exercise 9

Obviously, writing a separate function for each size tuple object will get pretty tedious. Since the code is so repetitive, there ought to be a way to write a single set of function templates that can calculate the distance from the origin to a point in n-dimensional space, given a representation of the location of that point as a tuple object with n elements. With a little template metaprogramming, the solution is fairly simple, although getting to it can be confusing.

We'll need a function template named distance that takes an arbitrary type T. If we assume that T is a specialization of tuple, we know from the previous exercises that we need to compute the sum of the squares of the elements of T and take the square root of that sum. We'll do that with a helper that calculates the sum of the squares of the elements of a tuple object; distance returns the square root of the value returned by that helper.

Let's look at implementing that helper. Here's where things start to get tricky. If the tuple that we're processing has one element, it's easy: The sum of the squares of the elements is simply the square of that one element. If our tuple has more than one element, the sum of the squares of its elements is the square of its first element plus the sum of the squares of the rest of its elements. This is a typical formulation for a problem that can be solved by recursion: We have a termination rule that handles the simplest case and a recursion rule that handles complex cases in terms of simpler ones. As long as each recursion results in a simpler case, we eventually bottom out at the termination case and can combine the intermediate results to get the answer. So our helper has to handle two cases: one in which we have only one element and the other in which we have more than one element. We can find out how many elements a tuple type has with the template tuple_size, and we can pick off individual elements with get. But there's a problem here: The index that we pass to get has to be a compile-time constant. Because of the limitations of template arguments to function templates, our helper has to be a class template, not a function template.

  1. Write a declaration for the class template distance_helper. The template should take two template arguments: a value elt of type size_t and a class type T. Don't give it a body.

  2. Write a partial specialization of distance_helper whose size_t argument is 0; it should still take an arbitrary type T. The specialization should have a static member function named eval that takes an argument of type const T&, assumes that T is a tuple type, and returns the square of the element at index 0 of T. This is the termination case.

  3. Write the general version of the template distance_helper. It should have a static member function named eval that takes an argument of type const T&. The function returns the square of the element at elt added to the sum of the squares of the remaining elt - 1 elements. Use distance_helper<elt -1, T> to calculate that sum. This is the recursion rule.

  4. Now all that's left is to call distance_helper's function eval from distance. Write the function distance. Caution: distance_helper takes the index of an element; the number of elements in a tuple object is not a valid index.

  5. Test the distance function with the following values:

    1. make_tuple(1.0)

    2. make_tuple(3.0, 4.0)

    3. make_tuple(3.5, 4.5, 5.5)

  6. What happens if you call distance with a tuple object that holds no elements?


Chapter 2. Smart Pointers

I shot an arrow into the air,

It fell to earth, I know not where.

"The Arrow and the Song"
HENRY WADSWORTH LONGFELLOW

Almost every nontrivial application controls some resource whose lifetime is intermediate between the lifetime of an auto object, which exists only while the function that defines it is executing, and the lifetime of a global object, which exists as long as the program is running. The most common resource with this sort of intermediate lifetime is memory, and experienced programmers are well aware of the problems that arise from errors in handling dynamically allocated memory. The TR1 library provides a pair of templatesshared_ptr, discussed in Section 2.4, and weak_ptr, discussed in Section 2.5that can help ensure that resources are available as long as they are needed and are properly disposed of when they are no longer needed.

An object of type shared_ptr<Ty> holds a pointer to an object of type Ty. If that pointer is not null, the object that the shared_ptr object points to is known as the controlled resource. The controlled resource can be reached through operator-> and through operator*, just as with an ordinary pointer.

A shared_ptr object also maintains a reference count for the controlled resource.[1] When you copy a shared_ptr object, the reference count is incremented; when you destroy a shared_ptr object,[2] the reference count is decremented. When the reference count becomes zero, the controlled resource will be released.

[1] This reference count doesn't have to actually exist anywhere; these templates can be implemented with linked lists, and in that case the reference count is the number of elements in a list.

[2] Typically by exiting from a block where the object was defined or by destroying an object that holds a shared_ptr object; you'll rarely, if ever, need to create shared_ptr objects with new.

An object of type weak_ptr<Ty> also holds a pointer to an object of type Ty, but weak_ptr objects do not change the reference count for the controlled resource. Thus, having weak_ptr objects that hold pointers to a controlled resource does not prevent releasing that resource. These objects can be used, for example, to break cycles in data structures.

In addition, it's sometimes convenient for a type to have a member function that returns a shared_ptr object that controls *this. This is done with the template enable_shared_from_this (discussed in Section 2.6).


Section 2.1. Definitions

2.1. Definitions

This section defines some terms used to explain the details of how shared_ptrs and weak_ptrs work.

A shared_ptr object owns a resource if it was

  • Contructed with a pointer to that resource

  • Constructed from a shared_ptr object that owns that resource

  • Constructed from a weak_ptr object that points to that resource

  • Assigned ownership of that resource either by operator= or by the member function reset; in this case, it no longer owns the resource, if any, that it owned before being assigned ownership of its new resource

A weak_ptr object points to a resource if it was

  • Constructed from a shared_ptr object that owns the resource

  • Constructed from a weak_ptr object that points to the resource

  • Assigned ownership of that resource by operator=; in this case, it no longer points to the resource, if any, that it pointed to before the assignment

More generally, an object controls a resource if it is a shared_ptr object that owns the resource or if it is a weak_ptr object that points to the resource.

An empty shared_ptr object does not own any resources. An empty weak_ptr object does not point to any resources.

Some functions assign control of a resource to an object. These functions are overloaded to obtain the resource from any of several sources; the properties of the object after the function returns depend on which version of the function was called. In the following sections, the names of the arguments are used to describe the source of the resource:

no arguments: the resulting object is empty.

ptr: a pointer of type Other* to the resource to be controlled. The type Ty must be a complete type. If the operation fails at runtimetypically by failing to allocate memoryit evaluates the expression delete ptr before exiting. If the operation succeeds, the resulting object is the original owner of the resource, and ptr is the original pointer to the resource.

ptr, dtor: a pointer of type Other* to the resource to be controlled and a deleter object for that resource. The type Ty must be a complete type. If it fails at runtimetypically by failing to allocate memorythe operation evaluates the expression dtor(ptr), which must be well defined, before exiting. See Section 2.10. If the operation succeeds, the resulting object is the original owner of the resource, and ptr is the original pointer to the resource.

sp: an object of type shared_ptr<Other>. The resulting object controls the resource that sp owns.

wp: an object of type weak_ptr<Other>. The resulting object controls the resource that wp points to.

ap: an object of type auto_ptr<Other> that holds a pointer to the resource to be controlled. If the operation succeeds, it calls ap.release(); otherwise, it leaves ap unchanged.

A shared_ptr object or a weak_ptr object releases control of a resource when the object is destroyed or when it is assigned control of a different resource.

When the last shared_ptr object that owns a resource releases control of that resource, the resource will be destroyed. When that happens, any remaining weak_ptr objects pointing to that resource have expired.

A controlled resource has a deleter if its original owner was assigned control of the resource by a function called with a pointer to the resource and a deleter object.


Section 2.2. About the Examples

2.2. About the Examples

Most of the examples in this chapter use a header file named "sputil.h". This header file defines a simple resource type, a stream inserter to display the contents of an object of that type, and a couple of function templates for displaying the state of various smart pointer objects. For details, see Appendix B.1.


Section 2.3. Header <memory> Synopsis

2.3. Header <memory> Synopsis

namespace std {
 namespace tr1 {

    // SHARED POINTERS
template<class Ty> class shared_ptr;
template<class Ty1, class Ty2>
  bool operator==(
    const shared_ptr <Ty1>& left,
    const shared_ptr <Ty2>& right);
template<class Ty1, class Ty2>
  bool operator!=(
    const shared_ptr <Ty1>& left,
    const shared_ptr <Ty2>& right);
template<class Ty1, class Ty2>
  bool operator<(
    const shared_ptr <Ty1>& left,
    const shared_ptr <Ty2>& right);
template<class Elem, class Tr, class Ty>
  std::basic_ostream<Elem, Tr>& operator<<(
    std::basic_ostream<Elem, Tr>& str,
    const shared_ptr<Ty>& sp);
template<class Ty>
  void swap(shared_ptr<Ty>& left, shared_ptr<Ty>& right);
template<class D, class Ty>
  D *get_deleter(const shared_ptr<Ty>& sp);

    // WEAK POINTERS
template<class Ty> class weak_ptr;
template<class Ty1, class Ty2>
  bool operator<(
    const weak_ptr<Ty1>& left,
    const weak_ptr<Ty2>& right);
template<class Ty>
  void swap(weak_ptr<Ty>& left, weak_ptr<Ty>& right);

    // UTILITY CLASSES AND TEMPLATES
template<class Ty> class enable_shared_from_this;
class bad_weak_ptr;

    // FUNCTIONS
template<class Ty, class Other>
  shared_ptr<Ty> const_pointer_cast(
    const shared_ptr<Other>& sp);
template<class Ty, class Other>
  shared_ptr<Ty> static_pointer_cast(
    const shared_ptr<Other>& sp);
template<class Ty, class Other>
  shared_ptr<Ty> dynamic_pointer_cast(
    const shared_ptr<Other>& sp);

} }


Section 2.4. The shared_ptr Class Template

2.4. The shared_ptr Class Template

template<class Ty> class shared_ptr {
public:
  typedef Ty element_type;

  shared_ptr();
  template<class Other>
    explicit shared_ptr(Other *ptr);
  template<class Other, class D>
    shared_ptr(Other *ptr, D dtor);
  shared_ptr(const shared_ptr& sp);
  template<class Other>
    shared_ptr(const shared_ptr<Other>& sp);
  template <class Other>
    shared_ptr(const weak_ptr<Other>& wp);
  template<class Other>
    shared_ptr(const std::auto_ptr<Other>& ap);
  ~shared_ptr();

  shared_ptr& operator=(const shared_ptr& sp);
  template<class Other>
    shared_ptr& operator=(const shared_ptr<Other>& sp);
  template<class Other>
    shared_ptr& operator=(auto_ptr<Other>& ap);

  void swap(shared_ptr& s);
  void reset();
  template<class Other>
    void reset(Other *ptr);
  template<class Other, class D>
    void reset(Other *ptr, D dtor);

  Ty *get() const;
  Ty& operator*() const;
  Ty *operator->() const;
  long use_count() const;
  bool unique() const;
  operator boolean-type() const;
  };

2.4.1. shared_ptr Summary

The template's default constructor can create an object of type shared_ptr<Ty> from a pointer to Ty or to a type that is derived from Ty, from another shared_ptr object, from a weak_ptr object, and from an auto_ptr object. These constructors are discussed in more detail in Section 2.4.2.

The destructor for shared_ptr is discussed in Section 2.4.3.

You can get to the controlled resource with operator-> and with operator*. You can get a pointer to the controlled resource with the member function get. These functions are discussed in Section 2.4.4.

A conversion operator tells you whether a shared_ptr object is empty. You can get the value of the reference count with the member function use_count, and you can check whether any other shared_ptr objects point to the same controlled resource with the member function unique. These functions are discussed in Section 2.4.5.

You can change a shared_ptr object so that it is empty or so that it controls a different resource. This is done with operator=, discussed in Section 2.4.6, or with the reset and swap member functions or the swap function template, discussed in Section 2.4.7.

Destruction of the controlled resource and the use of deleter objects are discussed in Section 2.9.

The implementation is allowed to throw exceptions when control of a newly created resource is assigned to a shared_ptr object.[3] The effects of such an exception are discussed in Section 2.10.

[3] This typically happens when not enough memory is available to create a manager object to track the original pointer and its reference count.

Several non-member templates can be used with shared_ptr objects. Tests for equality and inequality, as well as ordering, are discussed in Section 2.4.8. The stream inserter for shared_ptr objects is discussed in Section 2.4.9. The function template get_deleter is discussed in Section 2.4.10. Explicit type conversions are discussed in Section 2.8.3.

2.4.2. Constructing a shared_ptr Object

shared_ptr::shared_ptr ()

The default constructor constructs an empty shared_ptr object.

Example 2.1. Default Constructor for shared_ptr (smartptr/defcon.cpp)

#include <memory>
#include "sputil.h"
using std::tr1::shared_ptr;

int main()
  {
  shared_ptr<int> sp;           // default constructor
  show("default constructor", sp);
  return 0;
  }

template<class Other>
  explicit shared_ptr::shared_ptr(Other *ptr)
template<class Other, class D>
  shared_ptr::shared_ptr(Other *ptr, D dtor)

The constructors assign control (Section 2.1) of their arguments to the newly constructed shared_ptr object.

When you construct a shared_ptr object with a pointer that isn't null, you construct a shared_ptr object that owns the resource that the pointer points to.

Example 2.2. Construct from a Resource Pointer (smartptr/ptrcon.cpp)

#include <ostream>
#include <memory>
#include "sputil.h"
using std::tr1::shared_ptr;

int main()
  {
  shared_ptr<resource> sp(new resource(3));
  show("construct from pointer", sp);
  return 0;
  }

You can also construct a shared_ptr object from a pointer to a resource and a deleter object; when the last shared_ptr object that owns that resource releases control, the deleter object's operator() will be called with the resource pointer as its argument. For more details, see Section 2.9.

Example 2.3. Construct with a Deleter (smartptr/dtrcon.cpp)

#include <iostream>
#include <ostream>
#include <memory>
#include "sputil.h"
using std::tr1::shared_ptr;
using std::cout;

struct deleter
  {
  void operator()(resource *res)
    {
    cout << "destroying resource at"
         << (void*)res << '\n';
    delete res;
    }
  };

int main()
  {
  shared_ptr<resource> sp(new resource(3), deleter());
  show("construct from pointer", sp);
  return 0;
  }

These constructors can be called with a null pointer. This creates a slightly peculiar object; it technically isn't an empty shared_ptr object, even though it doesn't own any resources. See Section 2.4.8 for a discussion of how this affects comparison operators.

Example 2.4. Construct from a Null Pointer (smartptr/nullptrcon.cpp)

#include <ostream>
#include <memory>
#include "sputil.h"
using std::tr1::shared_ptr;

int main()
  {
  shared_ptr<resource> sp((resource*)0);
  show("construct from null pointer", sp);
  return 0;
  }

shared_ptr::shared_ptr(const shared_ptr & sp)
template<class Other>
  shared_ptr::shared_ptr(const shared_ptr <Other>& sp)

The constructors assign control (Section 2.1) of their arguments to the newly constructed shared_ptr object.

Don't use the same pointer to create two shared_ptr objects; if you do, the destructor for the controlled resource will be called twice when the shared_ptr objects are destroyed. Instead, copy the first shared_ptr object to create a second shared_ptr object that controls the resource.

Example 2.5. Copy a shared_ptr Object (smartptr/spcon.cpp)

#include <memory>
#include "sputil.h"
using std::tr1::shared_ptr;

int main()
  {
  shared_ptr<resource> sp0(new resource(4));
                                   // sp0 holds pointer to resource
  show("construct from pointer", sp0);
  shared_ptr<resource> sp1(sp0); // sp1 manages same object
                                   // as sp0
  show("construct from shared_ptr object", sp1);
  show("after copying", sp0);
  return 0;
  }   // sp1 destroyed, then sp0 destroyed

template<class Other>
  shared_ptr::shared_ptr(const weak_ptr<Other>& wp)

The constructors assign control (Section 2.1) of their arguments to the newly constructed shared_ptr object.

We'll look at constructing shared_ptr objects from weak_ptr objects when we talk about the weak_ptr template in Section 2.5.4.

template<class Other>
  shared_ptr::shared_ptr(const std::auto_ptr<Other>& sp)

The constructors assign control (Section 2.1) of their arguments to the newly constructed shared_ptr object.

Finally, the shared_ptr template has a constructor that takes an object of type std::auto_ptr<Other>. If the constructor succeeds, it calls release() on its argument, so the auto_ptr object no longer controls the resource. If the constructor failstypically by failing to allocate memoryit doesn't change the auto_ptr object.

Example 2.6. Construct from an auto_ptr Object (smartptr/apcon.cpp)

#include <memory>
#include "sputil.h"
using std::tr1::shared_ptr ; using std :: auto_ptr;

int main()
  {
  auto_ptr <resource> ap(new resource (5));
  show ("construct auto_ptr from pointer", ap);
  shared_ptr <resource> sp(ap);
  show ("auto_ptr", ap);
  show ("shared_ptr", sp);
  return 0;
  }

2.4.3. Destroying a shared_ptr Object

shared_ptr::~shared_ptr();

The destructor releases the controlled resource.

See Section 2.9 for details.

2.4.4. Accessing the Controlled Resource

Ty *shared_ptr::get() const;

The member function returns a pointer to the controlled resource.

Example 2.7. shared_ptr::get (smartptr/get.cpp)

#include <memory>
#include <iostream>
using std::tr1::shared_ptr;
using std::cout;

int main()
  { // demonstrate use of get
  int *ip = new int(3);                   // allocate int resource
  cout << (void*)ip >> '\n';              // show address
  shared_ptr<int> sp(ip);                 // create shared_ptr object
  cout << (void*)sp.get () >> '\n';       // show stored address
  return 0;
  }

Ty& shared_ptr::operator*() const;

The member function returns a reference to the controlled resource. If the object does not control any resource (get() == 0), the behavior is undefined.

Example 2.8. shared_ptr::operator* (smartptr/opstar.cpp)

#include <memory>
#include <iostream>
using std::tr1::shared_ptr;
using std::cout;

int main()
  { // demonstrate use of operator*

  int *ip = new int(3);               // allocate int resource
  cout << (void*)ip >> '\n';          // show address
  shared_ptr<int> sp(ip);             // create shared_ptr object
  cout << *sp >> '\n';                // show stored value
  cout << (void*)&*sp << '\n';        // show address of stored value
  return 0;
  }

Ty *shared_ptr::operator->() const;

The selection operator returns get(), so the expression sp->member behaves the same as (sp.get())->member, where sp is an object of class shared_ptr<Ty>. Hence, the stored pointer must not be null, and Ty must be a class, structure, or union type with a member member.

Example 2.9. shared_ptr::operator-> (smartptr/oparrow.cpp)

#include <memory>
#include <iostream>
using std::tr1::shared_ptr;
using std::cout;

struct S
  {
  int member;
  };

int main()
  { // demonstrate use of operator->
  S *s = new S;                            // create object
  s->member = 4;                           // assign to member
  shared_ptr<S> sp(s);                     // create shared_ptr object
  cout << sp -> member << '\n';            // show value of member
  return 0;
  }

2.4.5. Querying a shared_ptr Object's State

operator shared_ptr::operator boolean-type() const;

The conversion operator returns an object of an unspecified type that is convertible to bool. The resulting value is false if the object does not control a resource (get() == 0); otherwise, it is true.

Objects of shared_ptr types can be used in contexts that require a Boolean value. This conversion operator provides the usual pointer semantics: A value of false means that the shared_ptr object does not point to an actual resource, and a value of true means that it does.

Example 2.10. Conversion Operator (smartptr/boolconv.cpp)

#include <memory>
#include <iostream>
#include <string>
using std::tr1::shared_ptr;
using std::cout;
using std::string;

typedef shared_ptr<string> stp;

void show(stp s)
  { // show contents of target string
  if (s)
    cout << "string holds '" << *s << " '\n";
  else
    cout << "string is empty \n";
  }

int main()
  { // demonstrate conversion operator
  stp s;
  show(s);
  s.reset(new string("Hello, world"));
  show(s);
  return 0;
  }

The type returned by the conversion operator is up to the implementation.

Converting directly to bool can lead to problems because the resulting value can, in turn, be converted to a numeric value, so that an expresion like sp + 1, although an error, will compile and produce a value. Similarly, converting to void* leads to problems if someone writes delete sp. The TR1 specification recommends returning a pointer to member function, since you can do very few things accidentally with such a returned object.

long shared_ptr::use_count() const;

The member function returns the number of shared_ptr objects that own the resource controlled by *this. For an empty shared_ptr object, returns 0.

Example 2.11. shared_ptr::use_count (smartptr/spcount.cpp)

#include <memory>
#include <iostream>
using std::tr1::shared_ptr;
using std::cout;

typedef shared_ptr<int> spi;

int main()
  { // demonstrate member function use_count
  spi sp0 ;                          // empty object
  cout << "empty object: " << sp0.use_count() << '\n';
  spi sp1 ((int *)0);               // no resource
  cout << "null pointer: " << sp1.use_count() << '\n';
  spi sp2 (new int);                // controls resource
  cout << "one object: " << sp2.use_count() << '\n';
  { // create short-lived object
  spi sp3(sp2);                     // copy
  cout << "two objects: " << sp2.use_count() << '\n';
  } // sp3 destroyed
  cout << "one object: " << sp2.use_count() << '\n';
  return 0;
  }

bool shared_ptr :: unique () const;

The member function returns TRue if no other shared_ptr object owns the resource that is owned by *this; otherwise, false.

Example 2.12. shared_ptr::unique (smartptr/unique.cpp)

#include <memory>
#include <iomanip>
#include <iostream>
using std::tr1::shared_ptr;
using std::cout; using std::boolalpha;
typedef shared_ptr<int> spi;

int main()
  { // demonstrate member function unique
  cout << boolalpha;
  spi sp0;                          // empty object
  cout << "empty object: " << sp0.unique() << '\n';
  spi sp1((int *)0);                // no resource
  cout << "null pointer: " << sp1.unique() << '\n';
  spi sp2(new int);                 // controls resource
  cout << "one object: " << sp2.unique() << '\n';
  { // create short-lived object
  spi sp3(sp2);                     // copy
  cout << "two objects: " << sp2.unique() << '\n';
  } // sp3 destroyed
  cout << "one object: " << sp2.unique() << '\n';
  return 0;
  }

2.4.6. Assign to a shared_ptr Object

shared_ptr& shared_ptr::operator= (
  const shared_ptr& sp);
template<class Other>
  shared_ptr& shared_ptr::operator=(
    const shared_ptr<Other>& sp);
template<class Other>
  shared_ptr& shared_ptr::operator=(
    auto_ptr<Other>& ap);

Each of these operators releases the resource controlled by *this, if any, and assigns control (Section 2.1) of the resource on the right-hand side of the assignment to *this.

Example 2.13. Assign to a shared_ptr Object (smartptr/asgn.cpp)

#include <memory>
#include <iostream>
#include "sputil.h"
using std::tr1::shared_ptr; using std::auto_ptr;

typedef shared_ptr<resource> sps;
typedef auto_ptr<resource> aps;

static void asgn0()
  { // assign shared_ptr object to shared_ptr object
  sps sp0(new resource(1));                  // allocate resource
  show("construct sp0", sp0);
  sps sp1(new resource(2));                  // allocate resource
  show(" construct sp1", sp1);
  sp1 = sp0 ;                                 // assign, deallocate resource
  show("assign, sp0", sp0);
  show("assign, sp1", sp1);
  }

static void asgn1 ()
  { // assign auto_ptr object to shared_ptr object
  sps sp2(new resource(3));                   // allocate resource
  show("construct sp2", sp2);
  aps ap0(new resource(4));                   // allocate resource
  show("construct ap0", ap0);
  sp2 = ap0 ;                                 // assign, deallocate resource
  show("assign, ap0", ap0);
  show("assign, sp2", sp2);
  }

int main()
  { // demonstrate effects of assignment
  asgn0();
  asgn1();
  return 0;
  }

2.4.7. Modify a shared_ptr Object

void shared_ptr::reset();

The member function releases control of the object's controlled resource. After the function returns, *this is empty.

Example 2.14. shared_ptr::reset() (smartptr/reset.cpp)

#include <memory>
#include "sputil.h"
using std::tr1::shared_ptr;

int main()
  { // demonstrate member function reset()
  shared_ptr<resource> sp0;
  show("empty object before reset", sp0);
  sp0.reset();
  show("empty object after reset", sp0);
  shared_ptr<resource> sp1(new resource(1));
  show("non-empty object before reset", sp1);
  sp1.reset();
  show("non-empty object after reset", sp1);
  return 0;
  }

template<class Other>
  void shared_ptr::reset (Other *ptr);
template<class Other, class D>
  void shared_ptr::reset (Other *ptr, D dtor);

The member functions release control of the object's controlled resource and assign control of the resource pointed to by ptr to the object.

Example 2.15. shared_ptr::reset (smartptr/resetptr.cpp)

#include <memory>
#include "sputil.h"
using std::tr1::shared_ptr;

int main()
  { // demonstrate member function reset
  shared_ptr<resource> sp0;
  show("empty object before reset", sp0);
  sp0.reset (new resource(1));
  show("empty object after reset", sp0);
  sp0.reset(new resource(2));
  show("non-empty object after reset", sp0);
  return 0;
  }

void shared_ptr::swap(shared_ptr& sp);
template<class Ty>
  void swap(shared_ptr<Ty>& left, shared_ptr<Ty>& right);

The member function swaps the controlled resources between *this and sp. The function template calls left.swap(right).

Example 2.16. swap Functions (smartptr/swap.cpp)

#include <memory>
#include "sputil.h"
using std::tr1::shared_ptr;

int main()
  { // demonstrate member function swap
  shared_ptr<resource> sp0 (new resource(0));
  shared_ptr<resource> sp1 (new resource(1));
  show("sp0 before swap", sp0);
  show("sp1 before swap", sp1);
  sp0. swap (sp1);
  show("sp0 after swap", sp0);
  show("sp1 after swap", sp1);
  swap(sp0, sp1);
  show("sp0 after second swap", sp0);
  show("sp1 after second swap", sp1);
  return 0;
  }

2.4.8. Comparing shared_ptr Objects

Two shared_ptr<Ty> objects can be compared for equality and for relative order.

template<class Ty1, class Ty2>
  bool operator==(
    const shared_ptr<Ty1>& left,
    const shared_ptr<Ty2>& right);
template<class Ty1, class Ty2>
  bool operator!=(
    const shared_ptr<Ty1>& left,
    const shared_ptr<Ty2>& right);

The first function returns left.get() == right.get(). The second function returns !(left == right).

Example 2.17. Equality Comparisons (smartptr/spequal.cpp)

#include <memory>
#include <iomanip>
#include <iostream>
using std::tr1:: shared_ptr;
using std::cout; using std::boolalpha;

int main()
  {
  cout << boolalpha;
  shared_ptr<int> sp0(new int(0));
  shared_ptr<int> sp1(sp0);
  shared_ptr<int> sp2(new int(2));
  cout << "sp0 == sp1:" << (sp0 == sp1) << '\n';
  cout << "sp0 == sp2:" << (sp0 == sp2) << '\n';
  cout << "sp0 != sp1:" << (sp0 != sp1) << '\n';
  cout << "sp0 != sp2:" << (sp0 != sp2) << '\n';
  return 0;
  }

template<class Ty1, class Ty2>
  bool operator<(
    const shared_ptr<Ty1>& left,
    const shared_ptr<Ty2>& right);

The function defines a strict weak orderingas defined in [lib.alg. sorting] in the C++ standardon shared_ptr objects, with the additional constraint that !(left < right) && !(right < left) is true only if left and right are both empty or both control the same resource.

Because operator< defines a strict weak ordering, you can use shared_ptr objects as keys in associative containers.

Example 2.18. Less-Than Comparison (smartptr/splt.cpp)

#include <algorithm>
#include <memory>
#include <iostream>
#include <set>
using std::tr1::shared_ptr;
using std::lower_bound; using std::set;
using std::cout;

typedef shared_ptr<int> spi;
typedef set<spi> iset;
typedef iset::const_iterator citer;

static void lookup (const iset& data, spi sp)
  { // look for stored object that matches sp
  citer res = lower_bound(data.begin(), data.end(), sp);
  cout << *sp;
  if (res == data.end () || * res != sp)
    cout << "not found \n";
  else
    cout << "found\n";
  }

int main()
  { // demonstrate less-than comparison
  iset data;
  spi sp0(new int(0));
  spi sp1(new int(1));
  spi sp2(new int(2));
  spi sp3(sp1);           // shares ownership with sp1
  spi sp4(new int(1));    // same value as sp1, but different resource
  data.insert (sp0);
  data.insert (sp1);
  data.insert (sp2);
  lookup (data, sp1);    // search for sp1
  lookup (data, sp3);    // search for sp3
  lookup (data, sp4);    // search for sp4
  return 0;
  }

In this example, the call to lookup(data, sp1) succeeds because sp1 is in the container.[4] Similarly, the call to lookup(data, sp3) succeeds because sp3 is a copy of sp1, so it owns the same resource as sp1. However, the call to lookup(data, sp4) fails;sp4 owns a different resource, even though the two resources hold the same value.

[4] Actually, a copy of sp1 is in the container; the copy owns the same resource as the original.

Quirks: Empty Objects and Null Pointers

As we've just seen, !(left < right) && !(right < left) is true only if left and right are both empty or both control the same resource. Let's use that relation to define a new function template equiv, as follows:

template <class Ty1, class Ty2>
bool equiv(shared_ptr<Ty1> left, shared_ptr<Ty2> right)
  {
  return !(left < right) && !(right < left);
  }

That is, equiv returns TRue only if left and right are both empty or both control the same resource. As the name suggests, it is an equivalence relation; however, it's not the same equivalence relation as the one given by operator==. The member function shared_ptr::get() returns a null pointer when called on a shared_ptr<Ty> object that was constructed with the default constructor. It also returns a null pointer when called on a shared_ptr<Ty> object that was constructed with a null pointer, so an object constructed with the default constructor will compare equal to an object constructed with a null pointer. These two objects do not control the same resource, however, so a call to equiv with these two objects will return false. We'll look at this in more detail in one of the exercises.

2.4.9. Inserting shared_ptr Objects into Streams

template<class Elem, class Tr, class Ty>
  std::basic_ostream<Elem, Tr>& operator<<(
  std::basic_ostream<Elem, Tr>& str,
  const shared_ptr<Ty>& sp);

The function inserts sp.get() into the stream str.

Example 2.19. Stream Inserter (smartptr/inserter.cpp)

#include <memory>
#include <iostream>
using std::tr1::shared_ptr;
using std::cout;

int main()
  { // demonstrate stream inserter
  shared_ptr<int> sp(new int);
  cout << "   get: " << sp.get() < < '\n';
  cout << "object: " << sp << '\n';
  return 0;
  }

If you have an object of type shared_ptr<char>, the stream inserter will insert the resulting pointer to char. Just aswitha char*, if the pointer doesn't point to a null-terminated byte string, the result is unpredictable.

2.4.10. Function Template get_deleter

template<class D, class Ty>
  D *get_deleter(const shared_ptr<Ty>& sp);

If the argument sp has a deleter of type D, the function template returns a pointer to that deleter object; otherwise, it returns a null pointer.

Example 2.20. get_deleter (smartptr/getdeleter.cpp)

#include <memory>
#include <iostream>
using std::tr1::shared_ptr; using std::tr1::get_deleter;
using std::cout;

struct del
  { // trivial deleter object
  void operator ()(void *ptr)
    { // simply delete
    delete ptr;
    }
  };

int main()
  { // demonstrate function function get_deleter
  shared_ptr<int> sp0(new int);             // no deleter
  shared_ptr<int> sp1(new int, del());      // has deleter
  cout << get_deleter <del>(sp0) << '\n';
  cout << get_deleter <del>(sp1) << '\n';
  return 0;
  }


Section 2.5. The weak_ptr Class Template

2.5. The weak_ptr Class Template

template<class Ty> class weak_ptr {
public:
  typedef Ty element_type;

  weak_ptr();
  weak_ptr(const weak_ptr & wp);
  template<class Other>
    weak_ptr(const weak_ptr <Other>& wp);
  template<class Other>
    weak_ptr(const shared_ptr <Other>& sp);
  ~weak_ptr();

  weak_ptr& operator=(const weak_ptr & wp);
  template<class Other>
    weak_ptr& operator=(const weak_ptr<Other>& wp);
  template<class Other>
    weak_ptr& operator=(shared_ptr <Other>& sp);

  void swap(weak_ptr & wp);
  void reset();

  long use_count() const;
  bool expired() const;
  shared_ptr<Ty> lock() const;
  };

Objects of type weak_ptr<Ty> are used to break cycles in data structures.

A cycle occurs when two or more controlled resources hold pointers to one another so that the pointers form a loop. For example, if a node head contains a shared_ptr object that points to another node, N1, and the node N1 contains a shared_ptr object that points to head, the two nodes form a cycle. Because each node holds a pointer to the other, neither of the two reference counts can ever reach zero. The two nodes will not be deleted, even if no other shared_ptr objects are pointing to either of them. To break this cycle, N1 should hold a weak_ptr object that points to head, rather than a shared_ptr object. The code can still get from N1 back to head through the weak_ptr object, but when the last shared_ptr object that points to head is destroyed, the reference count for head will become zero, and head will be deleted; its destructor also destroys its shared_ptr object that points to N1, so the reference count for N1 will also become zero, and N1 will be destroyed.

Example 2.21. Weak Pointers (smartptr/weakptr.cpp)

#include <iostream>
#include <memory>
#include "sputil.h"
using std::tr1::shared_ptr; using std::tr1::weak_ptr;
using std::cout;

struct node : instrumented
  { // struct to demonstrate cycles
  shared_ptr<node> next;
  weak_ptr<node> weak_next;
  };

static void cycle ()
  { // constructs two nodes, destroys none
  cout << "Cycle:\n";
  node *head = new node;
  node *N1 = new node;
  shared_ptr<node> root(head);
  head->next = shared_ptr<node>(N1);
  N1->next = root;            // cycle
  }

static void no_cycle ()
  { // constructs two nodes, destroys both
  cout << "Break cycle:\n";
  node *head = new node;
  node *N1 = new node;
  shared_ptr<node> root(head);
  head->next = shared_ptr<node>(N1);
  N1-> weak_next = root;      // no cycle
  }

int main()
  { // demonstrate creating cycle and breaking cycle
  cycle ();
  no_cycle ();
  return 0;
  }

2.5.1. weak_ptr Summary

An object of type weak_ptr<Ty> can be created by the template's default constructor, by the constructor that takes a shared_ptr object, and by the constructor that takes another weak_ptr object. These constructors are discussed in Section 2.5.2.

The destructor for weak_ptr is discussed in Section 2.5.3.

You can't get to the controlled resource directly from a weak_ptr object. You have to create a shared_ptr object that owns the resource that the weak_ptr object points to and get to the controlled resource from there. You can create a shared_ptr object with the shared_ptr constructor that takes a reference to an object whose type is an instance of weak_ptr or with the member function weak_ptr::lock. These are discussed in Section 2.5.4.

To check whether a weak_ptr object has expired, use the member function expired. To get the value of the reference count for the controlled resource, use the member function use_count. These are discussed in Section 2.5.5.

You can change a weak_ptr object so that it points to a different controlled resource or to nothing. This is done with operator=, discussed in Section 2.5.6, or with the reset and swap member functions or the swap function template, discussed in Section 2.5.7.

The test for relative order of two weak_ptr objects is discussed in Section 2.5.8.

2.5.2. Constructing a weak_ptr Object

weak_ptr::weak_ptr();

The default constructor constructs an empty weak_ptr object.

Example 2.22. Default Constructor (smartptr/wpdefcon.cpp)

#include <memory>
#include "sputil.h"
using std::tr1::weak_ptr;

int main()
  {
  weak_ptr<int> sp;            // default constructor
  show("default constructor", sp);
  return 0;
  }

template<class Other>
  weak_ptr::weak_ptr(const shared_ptr <Other>& sp);

The constructor assigns control (Section 2.1) of its argument to the newly constructed shared_ptr object.

Example 2.23. Construct from shared_ptr (smartptr/wpspcon.cpp)

#include <memory>
#include "sputil.h"
using std::tr1::shared_ptr; using std::tr1::weak_ptr;

int main()
  { // demonstrate construction from shared_ptr
  shared_ptr <resource> sp(new resource(4));
                                    // sp owns resource
  show("shared_ptr", sp);
  weak_ptr<resource> wp(sp);        // wp points to resource
  show("weak_ptr", wp);
  return 0;
  }

weak_ptr::weak_ptr(const weak_ptr& wp);
template<class Other>
  weak_ptr::weak_ptr(const weak_ptr<Other>& wp);

The constructors assign control (Section 2.1) of their arguments to the newly constructed shared_ptr object.

Example 2.24. Construct from weak_ptr (smartptr/wpwpcon.cpp)

#include <memory>
#include "sputil.h"
using std::tr1::shared_ptr; using std::tr1::weak_ptr;

int main()
  { // demonstrate construction from shared_ptr
  shared_ptr<resource> sp(new resource(4));
                                      // sp owns resource
  weak_ptr<resource> wp0 (sp);        // wp0 points to resource
  weak_ptr<resource> wp1 (wp0);       // wp1 points to resource
  show("first weak_ptr", wp0);
  show("second weak_ptr", wp1);
  return 0;
  }

2.5.3. Destroying a weak_ptr Object

weak_ptr::~ weak_ptr();

The destructor releases the controlled resource.

See Section 2.9 for details.

2.5.4. Getting a shared_ptr Object

As mentioned earlier, you can't get from a weak_ptr object to its controlled resource directly; you have to create a shared_ptr object from that weak_ptr object. You can do that in two ways. You can construct a shared_ptr object, and you can call the member function lock. The key difference between the two is that if the weak_ptr object has expired, the shared_ptr constructor will throw an exception, but the lock member function will return an empty shared_ptr object.

template<class Other>
  shared_ptr::shared_ptr(const weak_ptr<Other>& wp);

If wp has expired, the constructor throws an object of type bad_weak_ptr. See Section 2.7 for the definition of this type. If wp is empty, the resulting shared_ptr object is also empty. Otherwise, the resulting shared_ptr object owns the resource that wp points to.

Example 2.25. Construct a shared_ptr Object (smartptr/spwpcon.cpp)

#include <iostream>
#include <memory>
#include "sputil.h"
using std::tr1::shared_ptr; using std::tr1::weak_ptr;
using std::tr1::bad_weak_ptr;
using std::cout;

int main()
  { // demonstrate constructing shared_ptr object from weak_ptr object
  weak_ptr<resource> empty_wp;
  show("empty weak_ptr", empty_wp);
  try
    { // try to construct from empty weak_ptr object
    shared_ptr<resource> sp0(empty_wp);
    }
  catch(const bad_weak_ptr&)
    { // catch resulting exception
    cout << "caught bad_weak_ptr object\n";
    }

  shared_ptr<resource> sp((resource *)0);
  weak_ptr<resource> wp1(sp);
  shared_ptr<resource> sp1(wp1);
  show("weak_ptr holding null pointer", wp1);
  show("copy of weak_ptr holding null pointer", sp1);

  sp.reset(new resource);
  weak_ptr<resource> wp2(sp);
  shared_ptr<resource> sp2(wp2);
  show("weak_ptr holding pointer to resource", wp2);
  show("shared_ptr holding pointer to resource", sp2);

  shared_ptr<resource> sp3(new resource);
  weak_ptr<resource> wp3(sp3);
  sp3.reset ();
  try
    { // try to construct from expired weak_ptr object
    shared_ptr <resource> sp4(wp3);
    }
  catch(const bad_weak_ptr&)
    { // catch resulting exception
    cout << "caught bad_weak_ptr object\n";
    }
  return 0;
  }

shared_ptr<Ty> weak_ptr::lock() const;

The member function returns an empty shared_ptr object if *this has expired; otherwise, shared_ptr(*this).

Example 2.26. weak_ptr::lock (smartptr/lock.cpp)

#include <memory>
#include "sputil.h"
using std::tr1::shared_ptr; using std::tr1::weak_ptr;

static void do_lock (const char *title,
  weak_ptr<resource> wp)
  {
  shared_ptr<resource> sp = wp.lock();
  show(title, sp);
  }

int main()
  { // demonstrate member function lock
  shared_ptr<resource> sp0(new resource);
  weak_ptr<resource> wp0(sp0);
  do_lock("weak_ptr with resource", wp0);
  sp0.reset();
  do_lock("expired weak_ptr", wp0);
  return 0;
  }

2.5.5. Query an Object's State

bool weak_ptr::expired() const;

The member function returns TRue only if the weak_ptr object has expired.

Example 2.27. weak_ptr::expired (smartptr/expired.cpp)

#include <iomanip>
#include <iostream>
#include <memory>
#include "sputil.h"
using std::tr1::shared_ptr; using std::tr1::weak_ptr;
using std::cout; using std::boolalpha;

int main()
  { // demonstrate member function expired
  cout << boolalpha;
  shared_ptr<resource> sp(new resource);
  weak_ptr<resource> wp(sp);
  cout << "points to resource: " << wp.expired () << '\n';
  sp.reset ();
  cout << "expired: " << wp.expired() << '\n';
  return 0;
  }

long weak_ptr::use_count ()const;

The member function returns the number of shared_ptr objects that own the resource controlled by *this. If the weak_ptr object is empty or expired, returns 0.

Example 2.28. weak_ptr::use_count (smartptr/wpcount.cpp)

#include <memory>
#include <iostream>
using std::tr1::shared_ptr; using std::tr1::weak_ptr;
using std::cout;

typedef shared_ptr<int> spi;
typedef weak_ptr<int> wpi;

int main()
  { // demonstrate member function use_count
  wpi wp0;                               // empty object
  cout << "empty object: " << wp0.use_count() << '\n';
  spi sp1((int *)0);                    // no resource
  wpi wp1(sp1);
  cout << "null pointer: " << wp1.use_count() << '\n';
  spi sp2(new int);                     // controls resource
  wpi wp2(sp2);
  cout << "one object: " << wp2.use_count() << '\n';
  { // create short-lived object
  spi sp3(sp2);                         // copy
  cout << "two objects: " << wp2.use_count() << '\n';
  } // sp3 destroyed
  cout << "one object: " << wp2.use_count() << '\n';
  sp2.reset ();
  cout << "expired: " << wp2.use_count() << '\n';
  return 0;
  }

2.5.6. Assigning to a weak_ptr Object

weak_ptr& weak_ptr::operator= (const weak_ptr& wp);
template<class Other>
  weak_ptr& weak_ptr::operator=(const weak_ptr <Other>& wp);
template<class Other>
  weak_ptr & weak_ptr::operator=(shared_ptr<Other>& sp);

Each of these operators releases the resource controlled by *this, if any, and assigns control (Section 2.1) of the resource on the right-hand side of the assignment to *this.

Example 2.29. Assign to a weak_ptr Object (smartptr/wpasgn.cpp)

#include <memory>
#include <iostream>
#include "sputil.h"
using std::tr1::shared_ptr; using std::tr1::weak_ptr;

typedef shared_ptr<resource> sps;
typedef weak_ptr<resource> wps;

int main()
  { // demonstrate effects of assignment
  sps sp0(new resource(1));             // allocate resource
  wps wp0;
  wp0 = sp0;
  show("assign to wp0", wp0);
  sps sp1(new resource(2));             // allocate resource
  wps wp1;
  wp1 = sp1;
  show("assign to wp1", wp1);
  wp1 = wp0;                            // assign
  show("assign, wp0", wp0);
  show("assign, wp1", wp1);
  show("assign, sp0", sp0);
  show("assign, sp1", sp1);
  return 0;
  }

2.5.7. Modifying a weak_ptr Object

void weak_ptr::reset();

The member function releases control of the object's controlled resource. After the function returns, *this is empty.

Example 2.30. reset (smartptr/wpreset.cpp)

#include <memory>
#include "sputil.h"
using std::tr1::shared_ptr; using std::tr1::weak_ptr;

int main()
  { // demonstrate member function reset()
  weak_ptr<resource> wp0;
  show("empty object before reset", wp0);
  wp0.reset();
  show("empty object after reset", wp0);
  shared_ptr<resource> sp1(new resource(1));
  weak_ptr<resource> wp1(sp1);
  show("non-empty object before reset", wp1);
  wp1.reset();
  show("non-empty object after reset", wp1);
  return 0;
  }

void weak_ptr::swap (weak_ptr& wp);
template<class Ty>
  void swap(shared_ptr<Ty>& left, shared_ptr<Ty>& right);

The member function swaps the controlled resources between *this and wp. The function template executes left.swap(right).

Example 2.31. swap Functions (smartptr/wpswap.cpp)

#include <memory>
#include "sputil.h"
using std::tr1::shared_ptr; using std::tr1::weak_ptr;

int main()
  { // demonstrate member function swap
  shared_ptr<resource> sp0(new resource(0));
  weak_ptr<resource> wp0(sp0);
  shared_ptr<resource> sp1(new resource(1));
  weak_ptr<resource> wp1(sp1);
  show("wp0 before swap", wp0);
  show("wp1 before swap", wp1);
  wp0.swap(wp1);
  show("wp0 after swap", wp0);
  show("wp1 after swap", wp1);
  swap(wp0, wp1);
  show("wp0 after second swap", wp0);
  show("wp1 after second swap", wp1);
  return 0;
  }

2.5.8. Comparing weak_ptr Objects

template<class Ty1, class Ty2>
  bool operator<(
    const weak_ptr<Ty1>& left,
    const weak_ptr<Ty2>& right);

The function defines a strict weak orderingas defined in [lib.alg. sorting] in the C++ standardon shared_ptr objects, with the additional constraint that !(left < right) && !(right < left) is true only if left and right control the same resource.

Because operator< defines a strict weak ordering, you can use shared_ptr objects as keys in associative containers. See also Section 2.4.8.

Example 2.32. Less-Than Comparison (smartptr/wplt.cpp)

#include <algorithm>
#include <memory>
#include <iostream>
#include <set>
using std::tr1::shared_ptr; using std::tr1::weak_ptr;
using std::lower_bound; using std::set;
using std::cout;

typedef shared_ptr<int> spi;
typedef weak_ptr<int> wpi;
typedef set<wpi> iset;
typedef iset::const_iterator citer;

static void lookup(const iset& data, wpi wp)
  { // look for stored object that matches wp
  citer res = lower_bound(data.begin(), data.end(), wp);
  spi sp0(wp);
  cout << *sp0;
  if (res == data.end() || spi (*res) != sp0)
    cout << " not found\n";
  else
    cout << " found\n";
  }

int main()
  { // demonstrate less-than comparison
  iset data;
  spi sp0(new int(0));
  spi sp1(new int(1));
  spi sp2(new int(2));
  spi sp3(sp1);                // shares ownership with sp1
  spi sp4(new int(1));         // same value as sp1,
                               // but different resource
  data.insert(wpi(sp0));
  data.insert(wpi(sp1));
  data.insert(wpi(sp2));
  lookup(data, wpi(sp1));     // search for sp1
  lookup(data, wpi(sp3));     // search for sp3
  lookup(data, wpi(sp4));     // search for sp4
  return 0;
  }


Section 2.6. The enable_shared_from_this Class Template

2.6. The enable_shared_from_this Class Template

template<class Ty>
  class enable_shared_from_this {
public:
  shared_ptr<Ty> shared_from_this();
  shared_ptr<const Ty> shared_from_this() const;
protected :
  enable_shared_from_this();
  enable_shared_from_this(const enable_shared_from_this&);
  enable_shared_from_this& operator=(
    const enable_shared_from_this&);
  ~ enable_shared_from_this();
  };

The member function shared_ptr::get gives you a pointer to the resource that a shared_ptr object owns. To go the other way, getting a shared_ptr object that owns the resource pointed to by a raw pointer, the obvious approach is to construct a shared_ptr object. However, if the resource is already owned by another shared_ptr object, you'll now have two shared_ptr objects that know nothing about each other and own the same resource. This will lead to problems, as both of the shared_ptr objects or their progeny will eventually try to delete the same object. To avoid this problem, types that will be managed through shared_ptr objects can provide a member function that returns a shared_ptr object that shares ownership with the original manager object. This is tricky to implement without tampering with the implementation of shared_ptr, so the class template enable_shared_from_this provides the member function shared_from_this.

To use the template enable_shared_from_this with a class Ty, make enable_shared_from_this<Ty> a public base of Ty:

class C : public enable_shared_from_this <C>
  {
  // ...
  };

Now if you create an object of type shared_ptr<C> from a pointer to a fully constructed object of type C [5] the shared_ptr code will make a note in the enable_shared_from_this base subobject, and its member function shared_from_this will return a shared_ptr<C> object that shares ownership with the shared_ptr<C> object that you created.

[5] Don't do this from C's constructor. It probably won't work.

2.6.1. Access

shared_ptr<Ty> enable_shared_from_this::shared_from_this();
shared_ptr<const Ty>
  enable_shared_from_this::shared_from_this() const;

The member functions return a shared_ptr object that shares ownership with the original owner of *this.

Example 2.33. shared_from_this (smartptr/enshared.cpp)

#include <memory>
#include <ostream>
#include "sputil.h"
using std::tr1::shared_ptr;
using std::tr1::enable_shared_from_this;
using std::basic_ostream;

struct C : enable_shared_from_this <C>, resource
  {
  C(int i0 = 0) : resource(i0) {}
  };

static void show_sp(C * cp)
  {
  shared_ptr<C>spc(cp->shared_from_this());
  show ("from this", spc);
  }
int main()
  {
  shared_ptr<C> sp(new C(1));
  show("original object", sp);
  C *cp = sp.get();
  show_sp(cp);
  show("after return", sp);
  return 0;
  }

2.6.2. Creation, Destruction, and Assignment

enable_shared_from_this::enable_shared_from_this();
enable_shared_from_this::enable_shared_from_this(
  const enable_shared_from_this&);
enable_shared_from_this& enable_shared_from_this::operator=(
  const enable_shared_from_this&);
enable_shared_from_this::~ enable_shared_from_this();

The constructors, destructor, and assignment operator do not throw exceptions.

These members are protected to help prevent accidental misuse. Make sure that your derived class calls them as appropriate.

Example 2.34. enable_shared_from_this (smartptr/enderive.cpp)

#include <memory>
#include "sputil.h"
using std::tr1::enable_shared_from_this;

class derived : public enable_shared_from_this<derived>
  {
  typedef enable_shared_from_this<derived> base;
public:
  derived() {}               // calls default constructor for base
  derived(const derived& der)
    : base(der) {}           // explicit call to copy constructor for base
  derived& operator =(const derived& der)
    {
    base::operator =(der);   // explicit call to assignment operator
    }
  ~derived () {}             // calls destructor for base
  };


Section 2.7. The bad_weak_ptr Class

2.7. The bad_weak_ptr Class

class bad_weak_ptr: public std::exception {
public:
  bad_weak_ptr();
  };

The class describes an exception that can be thrown when constructing a shared_ptr object that is a copy of a weak_ptr object and when assigning a weak_ptr object to a shared_ptr object.

See Section 2.5.2.


Section 2.8. Conversions

2.8. Conversions

In the examples we've looked at so far, the type Ty of the pointer held by a shared_ptr<Ty> or a weak_ptr<Ty> has been the same as the type of the resource pointer passed to the original owner of the resource. That's not required. You can construct a shared_ptr<Ty> object from a resource pointer Other*, and you can call shared_ptr::reset with a resource pointer Other*, provided that Other* is convertible to Ty*. See Section 2.8.1. You can also use copy constructors and assignments to convert shared_ptr<Other> and weak_-ptr<Other> objects to shared_ptr<Ty> and weak_ptr<Ty> objects, again provided that Other* is convertible to Ty*. See Section 2.8.2. Finally, you can call function templates that convert objects of type shared_ptr<Other> to objects of type shared_ptr<Ty> in much the same way that static_cast<Ty>, dynamic_cast<Ty>, and const_cast<Ty> do for ordinary pointers. See Section 2.8.3.

2.8.1. Pointer Conversions

template <class Other>
  explicit shared_ptr<Ty>::shared_ptr(Other *ptr);
template <class Other, class D>
  shared_ptr<Ty>::shared_ptr(Other *ptr, D dtor);
template <class Other>
  void shared_ptr<Ty>::reset(Other *ptr);
template <class Other, class D>
  void shared_ptr<Ty>::reset(Other *ptr, D dtor);

Each constructor constructs a shared_ptr<Ty> object that controls the resource pointed to by ptr.

The argument ptr must be convertible to a pointer of type Ty*; if it isn't, the code won't compile. The resulting object stores the original value of ptr; when the last owner of the resource is destroyed, the resource will be destroyed through that pointer. See Section 2.9.

Example 2.35. Pointer Conversions (smartptr/cnvptr.cpp)

#include <memory>
#include "sputil.h"
using std::tr1::shared_ptr;

int main()
  { // demonstrate pointer conversions
  shared_ptr<resource> sp(new d_res(1));
  show("constructed from pointer to derived", sp);
  sp.reset(new d_res(2));
  show("reset with pointer to derived", sp);
  return 0;
  }

2.8.2. Object Conversions

template <class Other>
  shared_ptr<Ty>::shared_ptr(const shared_ptr<Other>& wp);
template<class Other>
  weak_ptr<Ty>::weak_ptr(const shared_ptr <Other>& sp);
template<class Other>
  explicit shared_ptr<Ty>::shared_ptr(
    const weak_ptr<Other>& wp);
template <class Other>
  weak_ptr<Ty>::weak_ptr(const weak_ptr <Other>& wp);
template <class Other>
  shared_ptr<Ty>& shared_ptr<Ty>::operator=(
    const shared_ptr<Other>& sp);
template <class Other>
  weak_ptr<Ty>& weak_ptr<Ty>::operator=(
    const shared_ptr<Other>& sp);
template <class Other>
  weak_ptr<Ty>& weak_ptr<Ty>::operator=(
    const weak_ptr <Other>& wp);

Each function returns a shared_ptr<Ty> object or a weak_ptr<Ty> object that controls the resource that is controlled by its argument.

A pointer of type Other* must be convertible to a pointer of type Ty*; if it isn't, the code won't compile. The resulting object controls the same resource as the argument.

Example 2.36. Object Conversions (smartptr/cnvobj.cpp)

#include <memory>
#include "sputil.h"
using std::tr1::shared_ptr; using std::tr1::weak_ptr;

int main()
  { // demonstrate object conversions
  shared_ptr<d_res> spa(new d_res(1));
  weak_ptr<d_res> wpa(spa);

  shared_ptr<resource> sp0(spa);
  show("shared_ptr constructed from shared_ptr<d_res>",
    sp0);
  weak_ptr<resource> wp0(spa);
  show("weak_ptr constructed from shared_ptr<d_res>",
    wp0);
  shared_ptr<resource> sp1(wpa);
  show("shared_ptr constructed from weak_ptr<d_res>",
    sp1);
  weak_ptr<resource> wp1(wpa);
  show("weak_ptr constructed from weak_ptr<d_res>",
    wp1);

  shared_ptr<d_res> spb(new d_res(2));
  weak_ptr<d_res> wpb(spb);

  sp0 = spb;
  show("shared_ptr assigned from shared_ptr<d_res>",
    sp0);
  wp0 = spb;
  show("weak_ptr assigned from shared_ptr<d_res>",
    wp0);
  wp1 = wpb;
  show("weak_ptr assigned from weak_ptr<d_res>",
    wp1);
  return 0;
  }

2.8.3. Explicit Conversions

The conversions in the previous two sections are implicit conversions. They require the pointer type Other* to be implicitly convertible to the pointer type Ty*, so they act very much like that implicit pointer conversion. Just as with raw pointers, you'll sometimes need to convert shared_ptr objects to types that go the other way, that is, conversions that aren't inherently typesafe. With raw pointers, you make these conversions with various forms of casts; with shared_ptr objects, you use the function templates static_pointer_-cast, dynamic_pointer_cast, and const_pointer_cast.

template <class Ty, class Other>
  shared_ptr<Ty> static_pointer_cast(
    const shared_ptr<Other>& sp);

The function template returns shared_ptr<Ty>() if sp is empty; otherwise, it returns an object that acts like shared_ptr<Ty>(static_cast <Ty*>(sp.get()) but shares ownership of the resource that sp points to. If the expression static_cast<Ty*>(sp.get()) is not valid, the function is not valid.

Example 2.37. static_pointer_cast (smartptr/cnvstatic.cpp)

#include <memory>
#include "sputil.h"
using std::tr1::shared_ptr;
using std::tr1::static_pointer_cast;

int main()
  { // demonstrate static_pointer_cast
  shared_ptr<resource> sp(new d_res(1));
  shared_ptr<d_res> sp0 = static_pointer_cast<d_res>(sp
  show ("base resource", sp);
  show ("derived resource", sp0);

  sp. reset();
  sp0 = static_pointer_cast <d_res>(sp);
  show ("null pointer to base resource", sp);
  show ("null pointer to derived resource", sp0);
  return 0;
  }

template <class Ty, class Other>
  shared_ptr<Ty> dynamic_pointer_cast (
    const shared_ptr<Other>& sp);

The function template returns shared_ptr<Ty>() if sp is empty or if dynamic_cast<Ty*>(sp.get()) returns 0; otherwise, it returns an object that acts like shared_ptr<Ty>(dynamic_cast<Ty*>(sp.get()), but shares ownership of the resource that sp points to. If the expression dynamic_cast<Ty*>(sp.get()) is not valid, the function is not valid.

Example 2.38. dynamic_pointer_cast (smartptr/cnvdyn.cpp)

#include <memory>
#include "sputil.h"
using std::tr1::shared_ptr;
using std::tr1::dynamic_pointer_cast;

struct base0
  { // simple base class
  base0(int i0) : i(i0) {}
  virtual ~base0() {}
  int i;
  };

template <class Elem, class Tr>
std::basic_ostream<Elem, Tr>& operator <<(
  std::basic_ostream<Elem, Tr>& str,
  const base0& b0)
  { // insert base0 contents into stream
  return str << b0.i;
  }

struct base1
  { // simple base class
  base1(int j0) : j(j0) {}
  virtual ~base1 () {}
  int j;
  };

template <class Elem, class Tr>
std::basic_ostream<Elem, Tr>& operator<<(
  std::basic_ostream<Elem, Tr>& str,
  const base1& b1)
  { // insert base1 contents into stream
  return str << b1.j;
  }

struct derived : virtual base0, base1
  { // derived class
  derived (int i0, int j0, int k0)
    : base0 (i0), base1 (j0), k(k0) {}
  int k;
  };

template <class Elem, class Tr>
std::basic_ostream <Elem, Tr>& operator <<(
  std::basic_ostream<Elem, Tr>& str,
  const derived& d)
  { // insert derived contents into stream
  return str << d.k;
  }

int main()
  {
  shared_ptr<base0> sp(new derived(1, 2, 3));
  show("base0 shared_ptr", sp);
  shared_ptr<derived> sp0 =
    dynamic_pointer_cast<derived>(sp);
  show("upcast from virtual base", sp0);
  shared_ptr<base1> sp1 =
    dynamic_pointer_cast<base1>(sp);
  show("cross -cast", sp1);
  shared_ptr<resource> sp2 =
    dynamic_pointer_cast<resource>(sp);
  show("failed cast", sp2);
  return 0;
  }

template <class Ty, class Other>
  shared_ptr<Ty> const_pointer_cast(
    const shared_ptr<Other>& sp);

The function template returns shared_ptr<Ty>() if sp is empty; otherwise, it returns an object that acts like shared_ptr<Ty>(const_cast <Ty*>(sp.get()) but shares ownership of the resource that sp points to. If the expression const_cast<Ty*>(sp.get()) is not valid, the function is not valid.

Example 2.39. const_pointer_cast (smartptr/cnvconst.cpp)

#include <memory>
#include "sputil.h"
using std::tr1::shared_ptr;
using std::tr1::const_pointer_cast;

int main()
  { // demonstrate pointer conversions
  shared_ptr<const resource> sp(new resource (1));
  show("shared_ptr to const object", sp);
  shared_ptr<resource> sp0 =
    const_pointer_cast<resource>(sp);
  show ("shared_ptr to non-const object", sp0);
  return 0;
  }


Section 2.9. Destruction of Controlled Resources

2.9. Destruction of Controlled Resources

When the last shared_ptr object that owns a resource releases control of that resource, the resource will be destroyed. This is done with delete if the resource does not have a deleter; otherwise, with the deleter object. In both cases, the resource is destroyed through the original pointer to that resource, even if the type of that pointer is different from the template's type argument Ty.[6]

[6] Typically, the implementation allocates a manager object that holds the original pointer and its reference count; when the shared_ptr object is copied, the new object gets a pointer to the same manager object.

2.9.1. Resources without Deleter Objects

A resource that does not have a deleter object is destroyed by deleting the original pointer to that resource.

Example 2.40. Destroy a Resource, no Deleter (smartptr/destdtor.cpp)

#include <memory>
#include <iostream>
#include "sputil.h"
using std::tr1::shared_ptr;
using std::cout;

struct base0
  {
  base0 () : i(0) {}
  ~base0 ()
    {
    cout << "destroying base0 at"
         << (void*) this << '\n';
    }
  int i;
  };

struct base1
  {
  base1 () : j(1) {}
  ~base1 ()
    {
    cout << "destroying base1 at"
         << (void*) this << '\n';
    }
  int j;
  };

template <class Elem, class Tr>
std::basic_ostream<Elem, Tr>& operator <<(
  std::basic_ostream<Elem, Tr>& str,
  const base1& b1)
  { // insert base1 contents into stream
  return str << b1.j;
  }

struct derived : base0, base1
  {
  ~derived ()
    {
    cout << "destroying derived at"
         << (void*) this << '\n';
    }
  };

int main()
  {
  shared_ptr<base1> sp(new derived);
  show("shared_ptr object", sp);
  return 0;
  }

If you compile and run this example, you'll see that the shared_ptr<base1> object holds the address of the base1 subobject of the derived object. Nevertheless, when it goes out of scope at the end of main, its destructor destroys the resource through the original pointer to derived; the destructor for derived runs first, followed by the destructors for base0 and base1.[7]

[7] This is not a conclusive test for correctness. If the resource was being deleted through the pointer to base1, the behavior would be undefined; one possible symptom of this undefined behavior would be running the "right" destructor. However, with every compiler I've used, that wouldn't happen, so getting the right destructor usually means that the right pointer was deleted.

2.9.2. Resources with Deleter Objects

A resource that has a deleter object is destroyed by calling the deleter object's function call operator with the original pointer to that resource as argument. The deleter object is responsible for cleaning up the resource.

Example 2.41. Destroy a Resource with Deleter (smartptr/deleter.cpp)

#include <memory>
#include <iostream>
#include <ostream>
#include "sputil.h"
using std::tr1::shared_ptr;
using std::cout;

resource *get_resource(int i)
  { // allocate resource object
  resource *res = new resource(i);
  cout << "created resource with value"
    << *res << '\n';
  return res;
  }

void destroy_resource (resource *res)
  { // destroy resource object
  cout << "destroying resource with value"
    << *res << '\n';
  delete res;
  }

int main()
  { // demonstrate function pointer as deleter object
  shared_ptr<resource> sp(get_resource(3),
    destroy_resource);
  cout << "In main, resource has value "
    << *sp << '\n';
  return 0;
  }

In the main function, the constructor for sp is called with the pointer returned by get_resource and a pointer to the function destroy_resource. As a result, when sp goes out of scope, its destructor calls destroy_resource, passing the original pointer as its argument.

In this example, the function takes an argument whose type is the same as the type of the original pointer. In general, this need not be the case; all that's needed is that the deleter object can be called with a pointer of that type. For example, we could have used a type with a function call operator that takes a pointer to void:

struct resource_deleter
  {
  void operator()(void *ptr) { delete (resource *) ptr ; }
  };

The deleter object is passed by value, so all we need to do to use this type is to create a temporary object:

shared_ptr<resource> sp (get_resource(3),
  resource_deleter());


Section 2.10. Exceptions

2.10. Exceptions

When created, the first shared_ptr object that controls a particular resource allocates a control block from the heap. This allocation might fail, and the allocation code would throw an exception object of type bad_alloc. When that happens, the shared_ptr code that is creating the block will destroy the resource and rethrow the exception. This prevents memory leaks in typical code that looks like this:

shared_ptr<resource> sp(new resource(3));

If shared_ptr didn't do this, you'd have to store the pointer returned by new, enter a TRy block, initialize the shared_ptr object, and handle the possible exception by destroying the object. It's much easier to have that code in one place, inside the implementation of shared_ptr.

Example 2.42. Exceptions (smartptr/exceptions.cpp)

#include <memory>
#include <stdlib.h>
#include <iostream>
#include <new>
#include "sputil.h"
using std::tr1::shared_ptr;
using std::bad_alloc ; using std::cout;

static bool no_memory = false;

void *operator new(size_t sz)
  { // allocate memory, with one-shot failure
  void *res;
  bool no_mem = no_memory;
  no_memory = false;
  if (no_mem || (res = malloc (sz)) == 0)
    throw bad_alloc ();
  return res;
  }

void operator delete (void *ptr)
  { // free allocated memory
  free(ptr);
  }

int main()
  { // demonstrate resource destruction on exception
  try {  // construct with no memory
    cout << "construct with no memory :\n";
    instrumented *ip = new instrumented;
    no_memory = true;
    shared_ptr<instrumented> sp0(ip);
    }
  catch(...)
    { // handle the exception
    cout << " caught the exception \n";
    }
try { // reset with no memory
    cout << "reset with no memory:\n";
    shared_ptr<instrumented> sp1;
    instrumented *ip = new instrumented;
    no_memory = true;
    sp1.reset(ip);
    }
  catch(...)
    { // handle the exception
    cout << " caught the exception\n";
    }
  return 0;
  }


Section 2.11. Multithreading

2.11. Multithreading

Neither the C++ standard nor the TR1 library makes any promises about the behavior of C++ code in multithreaded applications (see Appendix C). However, library implementations typically try not to get in the way if you need to write multithreaded applications. This usually means avoiding coding practices that aren't safe in multithreaded applications. However, making shared_ptr and weak_ptr thread-safe requires internal synchronization, to prevent simultaneous conflicting changes to the reference counters. In practice, this means that shared_ptr and weak_ptr implementations that are thread-safe could be rather slow.[8]

[8] The most obvious implementation technique is to make every update a critical section, guarded by a mutex lock; that could be quite slow. It would be much faster to use atomic updates to avoid locking whenever possible, but the resulting code is rather fragile and notoriously difficult to test thoroughly.


Exercises

Exercise 1

For each of the following errors, write a simple test case containing the error, and try to compile it. In the error messages, look for the key words that relate to the error in the code.

  1. Attempting to construct a shared_ptr object with a pointer type that is not convertible to the pointer type held by the shared_ptr

  2. Attempting to construct a shared_ptr object with another shared_ptr object that holds a pointer type that is not convertible to the pointer type held by the object being constructed

  3. Attempting to construct a shared_ptr object with a pointer and a deleter object whose function call operator can't be called with the original pointer

  4. Attempting to convert a shared_ptr<int> to a shared_ptr<double> with static_pointer_cast

Exercise 2

Write a program that demonstrates the use of shared_ptr accessors. Begin by defining a simple struct that has one public data member and a default constructor that initializes that data member. Create a shared_ptr object that points to an object of this type. Display the value of the stored object's data member three times: once using shared_ptr::get(), once using shared_ptr::operator*, and once using shared_ptr::operator->.

Exercise 3

How many different ways can you think of to determine whether a shared_ptr object holds a non-null pointer? Write a program to verify that they all work correctly.

Exercise 4

Write a program consisting of a type definition, a function template, and a main function. The type definition should be a class whose constructor and destructor write logging messages to cout. (Use the instrumented class from sputil.h if you like). The function template should take an argument of an arbitrary type by value. Its body should simply write a logging message to cout, showing that it was called. In main, create an object of your logging type on the heap, and create a shared_ptr object to manage it. Call the function template with this shared_ptr object. Add logging messages to main so that you can see when the heap object is destroyed relative to the call to the function template. Do the same thing using an auto_ptr object to manage the heap object. Explain the output.

Exercise 5

Write a program that allocates an array of objects on the heap and manages that array with a shared_ptr object. Check that the array is properly deleted when it is no longer in use.

Exercise 6

I said in Section 2.4.2 that you shouldn't construct two shared_ptr objects from the same pointer. The danger is that both shared_ptr objects or their progeny will eventually try to delete the resource, and that usually leads to trouble. In fact, you can do this if you're careful. It's not particularly useful, but write a program that constructs two shared_ptr<instrumented> objects from the same pointer and deletes the resource only once.

Exercise 7

Write a program consisting of two functionsthe main function and a function named write. The write function should take an argument of type shared_ptr<FILE> and should write some text to the C-style stream identified by the FILE* held in the shared_ptr object. (Use the member function get() to get the pointer.) The main function should create two shared_ptr<FILE> objects. One should hold the pointer returned by a call to fopen and should properly close the stream when the last shared_ptr object managing that file is destroyed. The other should hold the pointer stdout and should not close the stream. The main function should call write with each of shared_ptr objects.

Exercise 8

Assume that you have the following objects:

// EMPTY shared_ptr OBJECTS
shared_ptr<int> sp0;
shared_ptr<int> sp1 (sp0);
shared_ptr<int> sp2;

// shared_ptr OBJECTS HOLDING NULL POINTERS
shared_ptr<int> sp3 ((int *)0);
shared_ptr<int> sp4 (sp3);
shared_ptr<int> sp5 ((int *)0);

// shared_ptr OBJECTS HOLDING NON-NULL POINTERS
shared_ptr<int> sp6 (new int (3));
shared_ptr<int> sp7 (sp6);
shared_ptr<int> sp8 (new int (3));

  1. What should the result of the following comparisons be?

    1. sp0 == sp1

    2. sp0 == sp2

    3. sp0 == sp3

    4. sp3 == sp4

    5. sp3 == sp5

    6. sp0 == sp6

    7. sp6 == sp7

    8. sp6 == sp8

  2. Write a program to verify your answers.

  3. Consider the following function:

    template <class Ty1, class Ty2>
bool equiv(shared_ptr<Ty1> left,
  shared_ptr<Ty2> right)
  {
  return !(left < right) && !(right < left);
  }

    Logically, it makes sense to say that left and right are equivalent if left is not less than right and right is not less than left. In fact, since operator< for shared_ptr types defines a strict weak ordering, it can be shown that equiv in turn is an equivalence relation, as its name suggests. In Section 2.4.8, we saw that this equivalence relation is required to be true only for objects that are empty or share ownership of the same resource. That's different from the rule for operator==. What should the result of the following function calls be?

    1. equiv(sp0, sp1)

    2. equiv(sp0, sp2)

    3. equiv(sp0, sp3)

    4. equiv(sp3, sp4)

    5. equiv(sp3, sp5)

    6. equiv(sp0, sp6)

    7. equiv(sp6, sp7)

    8. equiv(sp6, sp8)

  4. Write a program to verify your answers.

Exercise 9

  1. Use the function template equiv given in the previous exercise and the following data types and data objects:

    // TYPES
struct base1 {};
struct base2 {};
struct derived : base1, base2 {};

// OBJECTS
shared_ptr<derived> sp0(new derived);
shared_ptr<base1> sp1(sp0);
shared_ptr<base2> sp2(sp0);
shared_ptr<derived> sp3(new derived);

    What should the result of the following function calls be?

    1. equiv(sp0, sp1)

    2. equiv(sp0, sp2)

    3. equiv(sp1, sp2)

    4. equiv(sp3, sp1)

    5. equiv(sp3, sp2)

    Write a program to verify your answers.

  2. What should happen if you use == instead of equiv for the comparisons? Write a program to verify your answers.

Exercise 10

Write a program consisting of a function named do_search and a main function. The do_search function should take one argument of type shared_ptr<int> and one argument of type const std::vector<shared_ptr<int>>&. Assuming that the contents of the vector object are sorted, it should search for the shared_ptr<int> object in the vector object twice, first using the std::find algorithm and then using the std::binary_search algorithm, and report the results of both searches.

The main function should create several objects of type shared_ptr<int>, with each holding a pointer to an int object allocated on the heap. These int objects should all have different values. It should also create a shared_ptr<int> object that holds a null pointer and an empty shared_ptr<int> object. It should insert each of those shared_ptr<int> objects into an std:: vector<shared_ptr<int>> and use std::sort to sort the contents of the vector. Then it should do the following:

  1. Iterate through the container, showing the value, in order, of each of the int objects that the container elements control. Be careful not to dereference any null pointers.

  2. Call do_search, passing the empty shared_ptr object and the vector object.

  3. Call do_search, passing the shared_ptr object that holds a null pointer and the vector object.

  4. Call do_search, passing one of the shared_ptr objects that holds a non-null pointer and the vector object.

  5. Create another empty shared_ptr<int> object that is not a copy of the original one, and call do_search with the new object and the vector object.

  6. Create another shared_ptr<int> object that holds a null pointer and is not a copy of the original one, and call do_search with the new object and the vector object.

  7. Create another shared_ptr<int> object that holds a pointer to an int object allocated on the heap and is not a copy of any of the original ones. The value of the int object should be the same as the value of one of the original ones. Call do_search with the new object and the vector object.

Explain the results.

Exercise 11

A double-linked list consists of nodes that hold a data item, a pointer to the next node in the list, and a pointer to the previous node in the list. For purposes of this exercise, the last node in the list stores a null pointer as its pointer to its next node, and the first node in the list stores a null pointer as its pointer to its previous node. You access the contents of the list through a pointer that points to the first node in the list.

  1. Write a class template template <class Data> node that holds an object of type Data named data and two pointers named next and prev that point to other objects of type node<Data>. Write another class template, template <class Data> list, that holds a pointer named head that points to an object of type node<Data>. The constructor for this template should initialize head to 0. Add a member function void list::insert(const Data& val) that inserts a new node<Data> object holding the value val at the head of the linked list. Add a member function bool list::remove(const Data& val) that removes all nodes whose data member is equal to val from the list. Make sure that list's destructor deletes any nodes remaining in the list.

  2. Rewrite the previous example, using objects of type shared_ptr<node <Data>> instead of pointers in the template node and in place of the pointer named head in the template list. Remove the destructor from list; it shouldn't be needed, because you're now using shared_ptr objects instead of pointers. Why doesn't this version of list destroy the remaining nodes when the list object goes out of scope?

  3. Fix the memory leak in the previous example.

Exercise 12

Write three functions that each take a weak_ptr object and return a shared_ptr object. If the weak_ptr object has expired, the shared_ptr object returned by each function should be empty; otherwise, it should own the resource that the weak_ptr argument points to. Each function should, of course, use a different technique to make this determination. Write a program to verify that all three functions work correctly.

Exercise 13

In Section 2.8, we talked about implicit conversions between shared_ptr types and the three function templates for explicit conversions. Consider this class hierarchy:

class A { virtual void f () {} };
class B {};
class G : public A {};
class H : public B {};
class I : public virtual A {};
class J : public virtual B {};
class Z : public G, public H,
  public I, public J {};

  1. Beginning with an object shared_ptr<Z> spz(new Z), which of the following assignments is valid as written, which can be made valid with an explicit conversion, and which ones are simply not allowed?

    1. shared_ptr<G> spg = spz;

    2. shared_ptr<Z> t0 = spg;

    3. shared_ptr<A> spa0 = spg;

    4. shared_ptr<G> t1 = spa0;

    5. shared_ptr<H> sph = spz;

    6. shared_ptr<const B> spb0 = sph;

    7. shared_ptr<H> t2 = spb0;

    8. shared_ptr<I> spi = spz;

    9. shared_ptr<A> spa1 = spi;

    10. shared_ptr<I> t3 = spa1;

    11. shared_ptr<J> spj = spz;

    12. shared_ptr<B> spb1 = spj;

    13. shared_ptr<J> t4 = spb1;

    14. shared_ptr<G> spgx = spb1;

    15. shared_ptr<H> sphx = spa1;

  2. Write and compile some code to verify your answers.


Part II: Containers

    Chapter 3. Container Basics

    Chapter 4. The array Class Template

    Chapter 5. Unordered Associative Containers


Chapter 3. Container Basics

Ah, when she moved, she moved more ways than one:

The shapes a bright container can contain!

"I Knew a Woman"
THEODORE ROETHKE

The Standard Template Library, more commonly known as the STL, [1] is the invention of Dave Musser, Alex Stepanov, and Meng Lee. The design of the STL factors common programming tasks into four fundamental components: sequences, algorithms, iterators, and callable types.[2] As we'll see, the STL and the standard C++ library provide templates that aid in programming with all four of these components.

[1] Please don't refer to the standard C++ library as the STL.

[2] More commonly known by the rather confusing terms "function objects" and "functors," which we'll dismiss in Chapter 6.

In addition, the STL and the standard C++ library have several containers that hold sequences of elements. The TR1 library provides five new containers: a fixed-size array (Chapter 4), unordered sets, unordered multisets, unordered maps, and unordered multimaps (Chapter 5).


Section 3.1. STL Components

3.1. STL Components

A sequence is an ordered series of zero or more elements. An algorithm performs operations on the elements of a sequence, using iterators to access individual elements. An iterator is a generalization of a pointer; it can be dereferenced to get to the sequence element that it points to, and it can be incremented so that it points to the next element in the sequence.[3] One iterator is reachable from another iterator if it can be incremented zero or more times to get a value that compares equal to the other iterator. A range is a pair of iterators [first, last) where last is reachable from first. An input sequence is a range. The first iterator points to the current element, and the second iterator points to a position that's past the end of the sequence. When the two iterators compare equal, the sequence is empty. For example, an algorithm to find the maximum value in a nonempty sequence could be written like this:

[3] Iterators are more sophisticated than this sketch implies, but the additional details aren't needed here.

Example 3.1. Input Sequence (contbasic/input.cpp)

#include <iostream>
using std::cout;

template <class Iter>
Iter maximum(Iter first, Iter last)
  { // algorithm to find maximum value in nonempty sequence
  Iter res = first++;
  while (first != last)
    { // check current element
    if (*res < *first)
      res = first;
    ++first;
    }
  return res;
  }

int main()
  { // demonstrate use of input sequence
  const int NVALS = 6;
  int values[NVALS] = { 3,1,9,4,5,7};
  cout << "maximum: " <<
    *maximum(values, values + NVALS) << '\n';
  return 0;
  }

An output sequence is designated by a single iterator. If the iterator points to an element of a preexisting series of elements, assigning to the dereferenced iterator overwrites the value of the current element. In this case, an algorithm that writes to the output sequence must be written so that it doesn't write past the end of the sequence, either by passing an element count to the algorithm or by passing an input sequence that's no longer than the output sequence.

Example 3.2. Counted Output Sequence (contbasic/countoutput.cpp)

#include <iostream>
using std::cout;
template <class Iter>
void setcount(Iter first, int count)
  { // algorithm to write successive values to sequence
  for (int i = 0; i < count; ++i)
    *first++ = i;
  }

int main()
  { // demonstrate use of output sequence
  const int NVALS = 6;
  int values[NVALS];
  setcount (values, NVALS);
  for (int i = 0; i < NVALS; ++i)
    cout << values[i] << ' ';
  cout << '\n';
  return 0;
  }

The output sequence doesn't have to be a series of existing elements, however. An insert iterator creates a new element whenever the code assigns to the dereferenced iterator. The underlying sequence can be thought of as an unbounded series of uninitialized elements. Another form of iterator writes to a data sink, such as a file. In both cases, there is no neednor any way, in generalto check for the end of the output sequence.

Example 3.3. Unbounded Output Sequence (contbasic/unboundedoutput.cpp)

#include <iostream>
#include <iterator>
using std::iterator; using std::output_iterator_tag;
using std::cout;

struct write_iter : iterator <output_iterator_tag, int>
  { // iterator that writes to cout
  struct writer
    { // proxy with assignment operator
    template <class Ty> writer& operator=(const Ty& val)
      { // write the passed value
      cout << val << ' ';
      return *this;
      }
    };
  writer operator*() const

    { // return a proxy object
    return writer();
    }
  write_iter& operator++()
    { // do nothing
    return *this;
    }
  const write_iter& operator++(int)
    { // do nothing
    return *this;
    }
  };

template <class Iter>
void setcount (Iter first, int count)
  { // write successive values to sequence
  for (int i = 0; i < count; ++i)
    * first++ = i;
  }

int main()
  { // demonstrate use of unbounded output iterator
  const int NVALS = 6;
  setcount(write_iter(), NVALS);
  return 0;
  }

Some algorithms take a callable object[4] as one of their arguments. Algorithms that take a callable object with a unary function call operator typically call that object with each element in their input sequence.

[4] We'll look at callable objects in more detail in Chapter 6.

Example 3.4. Unary Callable Object (contbasic/unary.cpp)

#include <algorithm>
#include <functional>
#include <iostream>
using std::for_each; using std::unary_function;
using std::cout;

template <class Ty>
struct writer : unary_function<Ty, void>
  { // write values
  void operator()(const Ty& val)
    { // write the passed value
    cout << val << ' ';
    }
  };

int main ()
  { // demonstrate use of unary function object
  const int NVALS = 6;
  int values[NVALS] = { 3, 1, 9, 4, 5, 7 };
  for_each(values, values + NVALS, writer<int>());
  return 0;
  }

Algorithms that take a callable object with a binary function call operator call that object with two elements. For some algorithms, both elements come from a single input sequence; for others, they come from two input sequences.

Example 3.5. Binary Callable Object (contbasic/binary.cpp)

#include <functional>
#include <iostream>
using std::binary_function;
using std::cout;

template <class Ty>
struct lt : binary_function<Ty, Ty, bool>
  { // compare values
  bool operator()(const Ty& val0, const Ty& val1)
    { // return val0< val1
    return val0 < val1;
    }
  };

template <class Iter, class Cmp>
void merge (Iter first1, Iter last1,
  Iter first2, Iter last2,
  Iter dest, Cmp cmp)
  { // merge sorted ranges
  while (first1 != last1 && first2 != last2)
    { // copy lesser element to output sequence
    if (cmp (*first1, *first2))
      *dest++ = *first1++;
    else
      *dest++ =  *first2++;
    }
  while (first1 != last1)
    *dest++ = *first1++;
  while (first2 != last2)
    *dest++ = *first2++;
  }

int main()
  { // demonstrate use of binary function object
  const int NVAL0 = 6;
  const int NVAL1 = 7;
  const int NRES = NVAL0 + NVAL1;
  int values0[NVAL0] = { 1, 4, 9, 16, 25, 36 };
  int values1[NVAL1] = { 1, 1, 2, 3, 5, 8, 13 };
  int res[NRES];
  merge(values0, values0 + NVAL0,
    values1, values1 + NVAL1,
    res, lt<int>());
  for (int i = 0; i < NRES; ++i)
    cout << res[i] << ' ';
  cout << '\n';
  return 0;
  }


Section 3.2. Containers

3.2. Containers

In addition to the fundamental components described in the previous section, the STL and the standard C++ library provide a set of containers. Each container holds elements that can be stored and accessed according to a strategy that is specific to the container. The elements constitute the container's controlled sequence. You can access this sequence by calling the member functions begin and end, which return, respectively, an iterator that points to the first element in the controlled sequence and an iterator that points past the end of the controlled sequence.

Example 3.6. Container Iterators (contbasic/contiter.cpp)

#include <iostream>
#include <vector>
using std::cout;
using std::vector;

template <class Iter>
Iter maximum (Iter first, Iter last)
  { // find maximum value in nonempty sequence
  Iter res = first++;
  while (first != last)
    { // check current element
    if (*res < *first)
      res = first;
    ++first;
    }
  return res;
  }

int main ()
  { // demonstrate use of vector for input sequence
  const int NVALS = 6;
  int values[NVALS] = { 3, 1, 9, 4, 5, 7 };
  vector<int> vec(values, values + NVALS);
  cout << "maximum: " <<
    *maximum (vec.begin(), vec.end ()) << '\n';
  return 0;
  }

The standard C++ library has two kinds of containers: sequence containers and associative containers. In a sequence container, the elements are organized linearly. You can insert elements at any point in that linear sequence, and the order of the elements in the sequence pointed to by the iterators [begin(), end()) is determined by the locations where the elements were inserted.

Example 3.7. Sequence Container (contbasic/seqcont.cpp)

#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
using std::copy; using std::ostream_iterator;
using std::vector; using std::cout;

int main()
  { // show order of elements in sequence container
  vector <int> cont;
  cont.push_back(0);
  cont.push_back(2);

  cont.push_back(4);
  cont.push_back(1);
  cont.push_back(3);
  cont.push_back(5);
  copy(cont.begin(), cont.end(),
    ostream_iterator <int>(cout, " "));
  cout << '\n';
  return 0;
  }

Three sequence containers are in the standard C++ library. The container vector holds its elements in a contiguous array. This makes access to arbitrary elements fast but makes inserting new elements anywhere other than at the end slow. The container list holds its elements in a double-linked list. This makes access to arbitrary elements slow but makes inserting new elements anywhere in the container fast. The container deque typically holds its elements in multiple small arrays. This provides speeds that are intermediate between the speeds of vector and of list for accessing and inserting elements.

An associative container supports fast searching for elements that match a given key. The sequence pointed to by the iterators [begin(), end()) is ordered according to the values of the keys.[5]

[5] Associative containers are typically implemented with red-black trees.

Example 3.8. Associative Container (contbasic/assoccont.cpp)

#include <algorithm>
#include <iostream>
#include <iterator>
#include <set>
using std::copy; using std::ostream_iterator;
using std::set; using std::cout;

int main ()
  { // show order of elements in associative container
  set<int>cont;
  cont.insert(0);
  cont.insert(2);
  cont.insert(4);
  cont.insert(1);
  cont.insert(3);
  cont.insert(5);
  copy(cont.begin(), cont.end(),
    ostream_iterator<int>(cout, " "));
  cout << '\n';
  return 0;
  }

Four associative containers are in the standard C++ library. The container set supports searching for a key that has the same type as the container's elements. Duplicate elements are not allowed. The container multiset is like a set but allows duplicate elements. The container map holds elements of type pair<const Key, Value> and supports searching for a key of type Key. Thus, it associates a key and a value. Duplicate keys are not allowed. The container multimap is like a map but allows duplicate keys.

Containers can also be reversible. A reversible container is one with a bidirectional or a random-access iterator type. Reversible containers support iterating from the end of the container back toward the beginning. The member functions rbegin() and rend() return reverse iterators. The corresponding range, [rbegin(), rend()), iterates through the same elements as [begin(), end()) but in the opposite order. All the containers in the standard C++ library are reversible.

The TR1 library provides another kind of container. An unordered associative container, like an associative container, supports fast searching for elements that match a given key. Unlike an associative container, the sequence pointed to by the iterators [begin(), end()) is unspecified.[6]

[6] Unordered associative containers are typically implemented with hash tables.

Example 3.9. Unordered Container (contbasic/unordcont.cpp)

#include <algorithm>
#include <iostream>
#include <iterator>
#include <unordered_set>
using std::copy; using std::ostream_iterator;
using std::tr1::unordered_set;
using std::cout;

int main()
  { // show order of elements in unordered associative container
  unordered_set <int> cont;
  cont.insert(0);
  cont.insert(2);
  cont.insert(4);
  cont.insert(1);
  cont.insert(3);
  cont.insert(5);
  copy(cont.begin(), cont.end(),
    ostream_iterator<int>(cout, " "));
  cout << '\n';
  return 0;
  }

Four unordered associative containers are in the TR1 library. The container unordered_set is like set but doesn't require any particular order for the contained sequence. Similarly, unordered_multiset is like multiset, unordered_map is like map, and unordered_multimap is like multimap.


Further Reading

  • Generic Programming and the STL [Aus99] gives a detailed explanation of sequences, algorithms, iterators, callable types, and containers.

  • The C++ Standard Library [Jos99] discusses the entire standard C++ library, including sequences, algorithms, iterators, callable types, and containers.


Exercises

Exercise 1

Suppose that you have an array of 12 int values and 2 variables of type int*:

int values[12] = { 1, 1, 2, 3, 5, 8,
  13, 21, 34, 55, 89, 144 };
const int *first, *last;

After each of the following pairs of assignments, how many elements are in the sequence pointed at by the iterator range [first, last)? Write a program to verify your conclusions.

  1. first = values; last = values + 12;

  2. first = values + 1; last = values + 2;

  3. first = values; last = values;

  4. first = values + 12; last = values + 12;

Exercise 2

Repeat the previous example, using a vector<int> instead of an array to hold the int values and using a pair of iterators of type vector<int>::const_iterator instead of pointers.

Exercise 3

Write an algorithm that takes a pair of iterators designating a writable sequence of integer values. The algorithm should double each value in the controlled sequence and store the result in place of the original value. Test the algorithm by calling it on a sequence of integer values and displaying the result.

Exercise 4

Write a class that has a function call operator that takes an argument of type int and returns a value of type int that is twice the value of its argument. Modify the algorithm you wrote for the previous exercise to take a third template argument that provides the operation to perform on each element in the sequence. Test the new algorithm and the callable type by creating an object of the callable type and passing it to the algorithm along with a pair of iterators that points to a sequence of integer values and displaying the result.

Exercise 5

Rewrite the callable type that you wrote in the previous exercise so that its constructor takes a value that it stores in the object being constructed. Instead of multiplying by 2, the function call operator should multiply its argument by that stored value. Test the new callable type by creating an object that will multiply values by 3 and passing it to the algorithm that you wrote in the previous exercise.

Exercise 6

Insert a dozen or so values of type int, in no particular order, into an object of type vector<int>, and show the contents of the controlled sequence. Insert the same series of values into an object of type set<int>, and show the contents of the controlled sequence. Insert the same series of values into an object of type unordered_set<int>, [7] and show the contents of the controlled sequence.

[7] If you haven't looked ahead, use the header <unordered_set>. The template class unordered_set is in the namespace std::tr1.


Chapter 4. The array Class Template

Even Solomon in all his glory was not arrayed like one of these.

The Gospel According to Saint Matthew, 6:29

C-style arrays are tricky to use with STL algorithms. The size of the array is not part of its type, and the name of the array in almost all contexts decays into a pointer to its first element. So code that creates iterators into C-style arrays has to deal directly with the size of the array.

Example 4.1. C-style Arrays and the STL (contarray/carray.cpp)

#include <algorithm>
#include <iostream>
using std::cout; using std::sort;

void do_sort (int *values, int count)
  { // sort contents of array
  sort (values,  values + count);
  }

int main ()
  { // demonstrate use of C-style array as STL sequence
  const int ELEMS = 6;
  int values [ELEMS] = { 3, 1, 4, 2, 9, 8 };
  for (int i = 0; i < ELEMS;  ++i)
    cout << values[i]  << ' ';
  cout << '\n';
  do_sort (values, ELEMS);
  for (int i = 0; i < ELEMS ; ++i)
    cout << values[i]  << ' ';
  cout << '\n';
  return 0;
  }

The class template array<Ty, N> holds an array of N elements of type Ty. Its advantage over an ordinary array is that it directly supports some of the operations required for a sequence container.

Example 4.2. Class Template array and the STL (contarray/array.cpp)

#include <array>
#include <algorithm>
#include <iostream>
using std::cout; using std::sort;
using std::tr1::array;

template <class Container>
void do_sort (Container& values)
  { // sort contents of array
  sort (values.begin(), values.end());
  }

int main()
  { // demonstrate use C-style array as STL sequence
  const int ELEMS = 6;
  array<int, ELEMS> values = { 3, 1, 4, 2, 9, 8 };
  for (int i = 0; i < ELEMS ; ++i)
    cout << values [i] << ' ';
  cout << '\n';
  do_sort(values);
  for (int i = 0; i < ELEMS; ++i)
    cout << values[i] << ' ';
  cout << '\n';
  return 0;
  }

The class template itself, as well as several function templates that round out the support for the sequence container requirements and for a tuple-like interface, is defined in the header <array>.

namespace std {
 namespace tr1 {

template<class Ty, size_t N>
  class array;
    // FUNCTION TEMPLATES
template<class Ty, size_t N>
  bool operator==(
    const array<Ty, N>& left,
    const array<Ty, N>& right);
template<class Ty, size_t N>
  bool operator!=(
    const array<Ty, N>& left,
    const array<Ty, N>& right);
template<class Ty, size_t N>
  bool operator<(
    const array<Ty, N>& left,
    const array<Ty, N>& right);
template<class Ty, size_t N>
  bool operator<=(
    const array<Ty, N>& left,
    const array<Ty, N>& right);
template<class Ty, size_t N>
  bool operator>(
    const array<Ty, N>& left,
    const array<Ty, N>& right);
template<class Ty, size_t N>
  bool operator>=(
    const array<Ty, N>& left,
    const array<Ty, N>& right);
template<class Ty, size_t N>
  void swap(
    array<Ty, N>& left,
    array<Ty, N>& right);

    // tuple-LIKE INTERFACE
template<int Idx, class Ty, size_t N>
  Ty& get(array<Ty, N>& arr);
template<int Idx, class Ty, size_t N>
  const Ty& get(const array<Ty, N>& arr);
template<class Ty, size_t N>
  class tuple_element<array<Ty, N> >;
template<class Ty, size_t N>
  class tuple_size<array<Ty, N> >;

} }


Section 4.1. Class Template array

4.1. Class Template array

template<class Ty, size_t N>
  class array {
public:
  typedef size_t size_type;
  typedef ptrdiff_t difference_type;
  typedef Ty& reference;
  typedef const Ty& const_reference;
  typedef Ty *pointer;
  typedef const Ty *const_pointer;
  typedef T0 iterator;
  typedef T1 const_iterator;
  typedef Ty value_type;
  typedef reverse_iterator<iterator>reverse_iterator;
  typedef reverse_iterator<const_iterator>
    const_reverse_iterator;

  void assign(const Ty& val);
  void swap(array& right);

  iterator begin();
  const_iterator begin() const;
  iterator end();
  const_iterator end() const;
  reverse_iterator rbegin();
  const_reverse_iterator rbegin() const;
  reverse_iterator rend();
  const_reverse_iterator rend() const;

  size_type size() const;
  size_type max_size() const;
  bool empty() const;

  reference operator[](size_type off);
  const_reference operator[](size_type off) const;
  reference at(size_type off);
  const_reference at(size_type off) const;

  reference front();
  const_reference front() const;
  reference back();
  const_reference back() const;

  T *data();
  const T *data() const;
  };

An object of type array<Ty, N> holds N objects of type Ty in contiguous storage.[1]

Each specialization of the class template array is an aggregate, using only the compiler-generated default constructor, copy constructor, copy assignment operator, and destructor.

[1] Thus, given an object arr of type array<Ty, N>, for all values of n in the half-open range

[0,N), &arr[n] == &arr[0] + n.

An object of type array<Ty, N> can be constructed either with the default constructor, which uses the default constructor for Ty to initialize each of the stored elements, or with an aggregate initializer, which is an opening curly brace followed by zero to N comma-separated values, each of which must be convertible to the type Ty, followed by a closing curly brace. The compiler will use each of the initializer values to construct the corresponding element in the array object. If there are fewer than N initializers, the remaining elements are value-initialized.[2]

[2] For class types with non-trivial default constructors, value-initialization uses the default constructor. For class types with trivial default constructors, it value-initializes each member. For non-class types, it sets the value to 0.

Example 4.3. Construct an array Object (contarray/constructing.cpp)

#include <array>
#include <algorithm>
#include <iterator>
#include <ostream>
#include <iostream>
using std::tr1::array;
using std::basic_ostream; using std::cout;
using std::copy; using std::ostream_iterator;

class Elt
  { // class with non-trivial default constructor
public:
  Elt() : i (1) {}
  Elt(int ii) : i(ii) {}
private:
  template<class Elem, class Traits> friend
    basic_ostream<Elem, Traits>& operator<<(
      basic_ostream<Elem, Traits>&, const Elt&);
  int i;
  };

template<class Elem, class Traits>
  basic_ostream<Elem, Traits>& operator <<(
    basic_ostream<Elem, Traits>& out, const Elt& elt)
  { // show object contents
  return out << elt .i;
  }

int main()
  { // demonstrate default constructor and aggregate initialization
  array<Elt, 6> arr0;
  copy(arr0.begin(), arr0.end(),
    ostream_iterator <Elt>(cout, " "));
  cout << '\n';
  array<Elt, 6> arr1 = { 1, 2, 3, 4 };
  copy(arr1.begin(), arr1.end(),
    ostream_iterator <Elt >(cout, " "));
  cout << '\n';
  array<int, 6> arr2 = { 1, 2, 3, 4 };
  copy(arr2.begin(), arr2.end(),
    ostream_iterator<int>(cout, " "));
  cout << '\n';
  array<int, 6> arr3;
  copy(arr3.begin(), arr3.end(),
    ostream_iterator <int>(cout, " "));
  cout << '\n';
  array<int, 6> arr4 = {};
  copy(arr4.begin(), arr4.end(),
    ostream_iterator<int>(cout, " "));
  cout << '\n';
  return 0;
  }

An object of type array<Ty, N> can also be used to initialize another object of the same type, and an object of type array<Ty, N> can be assigned to another object of the same type.

Example 4.4. Copy an array Object (contarray/copying.cpp)

#include <array>
#include <algorithm>
#include <iterator>
#include <ostream>
#include <iostream>
using std::tr1::array;
using std::basic_ostream; using std::cout;
using std::copy; using std::ostream_iterator;

int main()
  { // demonstrate copying
  cout << "Original array: ";
  array<int, 6> arr0 = { 1, 1, 2, 3, 5, 8 };
  copy(arr0.begin(), arr0.end(),
    ostream_iterator<int>(cout, " "));
  cout << "\n  Copied array: ";
  array<int, 6> arr1 = arr0;
  copy(arr1.begin(), arr1.end(),
    ostream_iterator<int>(cout, " "));
  cout << "\n  New array: ";
  array<int, 6> arr2 = {};
  copy(arr2.begin(), arr2.end(),
    ostream_iterator<int>(cout, " "));
  cout << "\n  After copy: ";
  arr2 = arr0;
  copy(arr2.begin(), arr2.end(),
    ostream_iterator<int>(cout, " "));
  cout << '\n';
  return 0;
  }


Section 4.2. Queries

4.2. Queries

All containers have three member functions that provide information about the size of their controlled sequence. For array objects, these functions are very simple, because the size never changes.

size_type array<Ty, N>::size() const;

The member function returns N, the number of elements in the controlled sequence.

size_type array<Ty, N>::max_size() const;

The member function returns N, the maximum possible number of elements in the controlled sequence.

bool array<Ty, N>::empty() const;

The member function returns N == 0.


Section 4.3. Access

4.3. Access

reference array<Ty, N>::operator[](size_type off);
const_reference
  array<Ty, N>::operator[](size_type off) const;

The member functions return a reference to the element of the controlled sequence at position off. If the position is invalid, the behavior is undefined.

These functions provide the usual indexed access to elements of an array. Note that the implementation is not required to check the index value against the bounds of the array. If there is a possibility of getting an index value that is out of bounds, the calling code should check the value before calling these operators.

Example 4.5. Checking Index Values (contarray/indexing.cpp)

#include <array>
#include <iostream>
using std::tr1::array;
using std::cin; using std::cout;

const int ELEMS = 10;
array<int, ELEMS> squares = { 0, 1, 4, 9, 16,
  25, 36, 49, 64, 81 };

int main()
  { // demonstrate array indexing
  int idx = -1;
  while (idx <0 || ELEMS <= idx)
    { // check index value before using
    cout << "Value to square: ";
    cin >> idx;
    }
  cout << idx << " squared is "
    << squares [idx] << "\n\n";

  // no check needed:
  for (idx = 0; idx < ELEMS; ++idx)
    cout << idx << " squared is "
      << squares[idx] << '\n';
  return 0;
  }

reference array<Ty, N>::at(size_type off);
const_reference array<Ty, N>::at(size_type off) const;

The member functions return a reference to the element of the controlled sequence at position off. If the position is invalid, the function throws an object of class std::out_of_range.

These functions provide indexed access to elements of an array. The index value is checked against the bounds of the array; if the value is out of bounds, the function throws an exception. It's tempting to use this function to avoid validating input, but it's usually better to make the range check explicit. Exceptions should be reserved for truly exceptional situations and not used for control flow.

Example 4.6. Implicit Checking of Index Values (contarray/at.cpp)

#include <array>
#include <iostream>
#include <stdexcept>
using std::tr1::array;
using std::cin; using std::cout; using std::out_of_range;

const int ELEMS = 10;
array<int, ELEMS> squares = { 0, 1, 4, 9, 16,
  25, 36, 49, 64, 81 };

int main()
  { // demonstrate index checking with array::at
  int idx = -1;
  for (;;)
    { // don't do this:
    try { // show the value
        cout << idx << " squared is "
          << squares .at(idx) << '\n';
        break;
        }
    catch(const out_of_range&)
      { // prompt for new index value
      cout << "Value to square: ";
      cin >> idx;
      }
    }
  return 0;
  }

reference array<Ty, N>::front();
const_reference array<Ty, N>::front() const;

The member functions return a reference to the first element of the controlled sequence. If the controlled sequence is empty, the behavior is implementation-defined.

reference array<Ty, N>::back();
const_reference array<Ty, N>::back() const;

The member functions return a reference to the last element of the controlled sequence. If the controlled sequence is empty, the behavior is implementation-defined.

T *array<Ty, N>::data();
const T *array<Ty, N>::data() const;

The member functions return a pointer to the first element of the controlled sequence or, for an empty sequence, a non-null pointer that cannot be dereferenced.

As mentioned earlier, the elements of an array object are contiguous. As a result, the pointer returned by data() is a pointer to a C-style array of N objects of type Ty.

Example 4.7. C-Style Array of Objects (contarray/data.cpp)

#include <array>
#include <stdlib.h>
#include <iostream>
using std::tr1::array;
using std::cout;

int lt(const void *left, const void *right)
  { // compare int values pointed to by left and right
  int il = *(int*)left;
  int ir = *(int*)right;
  return il < ir ? -1 : il == ir ? 0 : 1;
  }

const int ELEMS = 6;

int main()
  { // demonstrate use of array::data() as C-style pointer
  array<int, ELEMS> values = { 3, 1, 4, 2, 9, 8 };
  for (int i = 0; i < ELEMS; ++i)
    cout << values [i] << ' ';
  cout << '\n';
  qsort(values.data(), ELEMS, sizeof(int), lt);
  for (int i = 0; i < ELEMS; ++i)
    cout << values[i] << ' ';
  cout << '\n';
  return 0;
  }


Section 4.4. Modification

4.4. Modification

Individual elements of a non-const array object can be modified through the reference returned by operator[] or the member function at. Multiple elements can be modified by calling assign or swap.

void array<Ty, N>::assign(const Ty& val);

The member function replaces the controlled sequence with a repetition of N elements of value val.

This function simply assigns the value val to all the elements in the array object. Be careful, though, when you use array objects in generic code: The signature of this function is not the same as the signature of the member function assign for sequence containers. That function takes an element count as its first argument and creates a new sequence with the specified number of elements. Since the number of elements in an array object is fixed, passing this argument to the member function would be pointless.

void array<Ty, N>::swap(array& right);

The member function swaps the controlled sequences between *this and right in linear time.

template <class Ty, size_t N>
  void swap(array<Ty, N>& left, array<Ty, N>& right);

The function template calls left.swap(right).

The swap functions exchange the contents of two array objects of the same type. However, the time they take is proportional to the size of the array objects, so they do not meet the sequence container requirement that swap run in constant time.


Section 4.5. Iteration

4.5. Iteration

iterator array<Ty, N>::begin();
const_iterator array<Ty, N>::begin() const;

The member functions return a random-access iterator that points to the first element of the controlled sequence or just beyond the end of an empty sequence.

iterator array<Ty, N>::end();
const_iterator array<Ty, N>::end() const;

The member functions return a random-access iterator that points just beyond the end of the controlled sequence.

The member functions begin and end return a pair of iterators that designate the beginning and the end of the controlled sequence.

Example 4.8. Calling an Algorithm (contarray/beginend.cpp)

#include <array>
#include <algorithm>
#include <iostream>
#include <iterator>
using std::tr1::array;
using std::sort;
using std::cout; using std::copy;
using std::ostream_iterator;

const int ELEMS = 6;

int main()
  { // demonstrate use of begin and end to designate range
  array<int, ELEMS> values = { 3, 1, 4, 2, 9, 8 };
  copy(values.begin(), values.end(),
    ostream_iterator<int>(cout, " "));
  cout << '\n';
  sort(values.begin(), values.end());
  copy(values.begin(), values.end(),
    ostream_iterator<int>(cout, " "));
  cout << '\n';
  return 0;
  }

reverse_iterator array<Ty, N>::rbegin();
const_reverse_iterator array<Ty, N>::rbegin() const;

The member functions return a random-access iterator that points just beyond the end of the controlled sequence. Hence, it designates the beginning of the reverse sequence.

reverse_iterator array<Ty, N>::rend();
const_reverse_iterator array<Ty, N>::rend() const;

The member functions return a random-access iterator that points to the first element of the controlled sequence or just beyond the end of an empty sequence. Hence, it designates the end of the reverse sequence.

The member functions rbegin and rend return a pair of iterators that designate the beginning and the end of the controlled sequence in reverse.

Example 4.9. Reversing an Algorithm (contarray/rbeginrend.cpp)

#include <array>
#include <algorithm>
#include <iostream>
#include <iterator>
using std::tr1::array;
using std::sort;
using std::cout; using std::copy;
using std::ostream_iterator;

const int ELEMS = 6;

int main()
  { // demonstrate use of rbegin and rend to designate range
  array<int, ELEMS> values = { 3, 1, 4, 2, 9, 8 };
  copy(values.begin(), values.end(),
    ostream_iterator<int>(cout, " "));
  cout << '\n';
  sort(values.rbegin(), values.rend());
  copy(values.begin(), values.end(),
    ostream_iterator<int>(cout, " "));
  cout << '\n';
  return 0;
  }


Section 4.6. Nested Type Names

4.6. Nested Type Names

The class template array provides all the nested type names required for sequence containers in the standard C++ library.

typedef size_t array<Ty, N>::size_type;

The unsigned integer type describes an object that can represent the length of any controlled sequence. It is required to be a synonym for the type size_t.

typedef ptrdiff_t array<Ty, N>::difference_type;

The signed integer type describes an object that can represent the difference between the addresses of any two elements in the controlled sequence. It is required to be a synonym for the type ptrdiff_t.

typedef Ty& array<Ty, N>::reference;

The type describes an object that can serve as a reference to an element of the controlled sequence. It is required to be a synonym for the type Ty&.

typedef const Ty& array<Ty, N>::const_reference;

The type describes an object that can serve as a reference to an element of the controlled sequence. The reference type does not permit modification of the referenced element. It is required to be a synonym for the type const Ty&.

typedef Ty *array<Ty, N>::pointer;

The type describes an object that can serve as a pointer to an element of the controlled sequence. It is required to be a synonym for the type Ty*.

TR1 doesn't actually require the nested type pointer, but that seems to be an oversight.

typedef const Ty *array<Ty, N>::const_pointer;

The type describes an object that can serve as a pointer to an element of the controlled sequence. The pointer type does not permit modification of the element it points to. It is required to be a synonym for the type const Ty*.

TR1 doesn't actually require the nested type const_pointer, but that seems to be an oversight.

typedef T0 array<Ty, N>::iterator;

The type describes an object that can serve as a random-access iterator for the controlled sequence. It is described here as a synonym for the implementation-defined type T0.

Just as with std::vector, the type of an iterator is not required to be a pointer to the contained type. When you write code that stores iterators explicitlywhich you should do only rarely, if at alluse the nested type name:

typedef array<int, 10> data;
data values;
data::iterator iter =
    values.begin();              // if you insist
int *pointer = values.begin();   // wrong, but might compile

typedef T1 array<Ty, N>::const_iterator;

The type describes an object that can serve as a random-access iterator for the controlled sequence. The iterator type does not permit modification of the element it points to. It is described here as a synonym for the implementation-defined type T1.

typedef Ty array<Ty, N>::value_type;

The type is a synonym for the template parameter Ty.

typedef reverse_iterator<iterator>
  array<Ty, N>::reverse_iterator;

The type describes an object that can serve as a reverse iterator for the controlled sequence.

typedef reverse_iterator<const_iterator>
  array<Ty, N>::const_reverse_iterator;

The type describes an object that can serve as a reverse iterator for the controlled sequence. The iterator type does not permit modification of the element it points to.


Section 4.7. Comparisons

4.7. Comparisons

template<class Ty, size_t N>
  bool operator==(
    const array<Ty, N>& left,
    const array<Ty, N>& right);

The function template overloads operator== to compare two objects of class template array. The function returns equal(left.begin(), left. end(), right.begin()).

This is the usual definition of equality: Two containers are equal if their corresponding elements are equal.

template<class Ty, size_t N>
  bool operator!=(
    const array<Ty, N>& left,
    const array<Ty, N>& right);

The function template overloads operator!= to compare two objects of class template array. The function returns !(left == right).

template<class Ty, size_t N>
  bool operator<(
    const array<Ty, N>& left,
    const array<Ty, N>& right);

The function template overloads operator< to compare two objects of class template array. The function returns lexicographical_compare (left.begin(), left.end(), right.begin()).

This is the usual definition of less-than: One container is less than another if, in the first pair of unequal elements, the element from the first container is less than the element from the second container.

template<class Ty, size_t N>
  bool operator<=(
    const array<Ty, N>& left,
    const array<Ty, N>& right);

The function template overloads operator<= to compare two objects of class template array. The function returns !(right < left).

template<class Ty, size_t N>
  bool operator>(
    const array<Ty, N>& left,
    const array<Ty, N>& right);

The function template overloads operator> to compare two objects of class template array. The function returns right < left.

template<class Ty, size_t N>
  bool operator>=(
    const array<Ty, N>& left,
    const array<Ty, N>& right);

The function template overloads operator>= to compare two objects of class template array. The function returns !(left < right).


Section 4.8. The tuple-like Interface

4.8. The tuple-like Interface

The type array<Ty, N> is similar to the type tuple<Ty, Ty, ..., Ty> with N arguments of type Ty, so the TR1 library provides a set of overloaded function templates that can be applied to array objects in the same way that they can be applied to tuple objects.

template<int Idx, class Ty, size_t N>
  Ty& get(array<Ty, N>& arr);
template<int Idx, class Ty, size_t N>
  const Ty& get(const array<Ty, N>& arr);

The function templates return a reference to arr[Idx]. If Idx < 0 or N <= Idx, the program is ill formed.

template<class Ty, size_t N>
  class tuple_element<array<Ty, N> >;

The class template holds a nested type named type that is a synonym for the template parameter Ty.

template<class Ty, size_t N>
  class tuple_size<array<Ty, N> >;

The class template holds a compile-time constant named value of an unspecified integral type whose value is the template parameter N.


Exercises

Exercise 1

For each of the following errors, write a simple test case containing the error, and try to compile it. In the error messages, look for the key words that relate to the error in the code.

  1. Attempting aggregate initialization of an array object with more initializers than the number of elements it holds

  2. Attempting default construction of an array object holding elements whose type does not have a default constructor

  3. Attempting aggregate initialization with a type that cannot be converted to the type of elements the array type holds

  4. Attempting copy construction from an array object of a different type

  5. Attempting to call get with an index value that is out of bounds

Exercise 2

Write a struct named elt that holds a value of type unsigned char but doesn't initialize it. Create an object of type std::tr1::array<elt, 6> with no initializer, and show the stored values. Now write a new struct, elt1, that holds a value of type unsigned char and has a default constructor that sets the stored value to 1. Create an object of type std::tr1::array <elt1, 6> with no initializer, and show the stored values.

Exercise 3

Repeat the preceding exercise, but when you create each array object, use an aggregate initializer that initializes some but not all of the stored objects. (You'll have to add another constructor to elt1. It should take a value of type unsigned char and copy it to the stored value.)

Exercise 4

Create an object of type array<int, 6> that initially holds all 0s. Change all its stored values to 1. Create an object of type array<int, 6> that initially holds all 1s. Change all its stored values to 0.

Exercise 5

Create two objects of type array<int, 6>. The first one should contain the values 1 through 6 in ascending order. The second one should contain the value 1, 2, 3, 3, 9000, and 9001, in that order. Which of the two is less than the other? Write a test program to verify your answer.

Exercise 6

Repeat Exercise 5 from Chapter 1 with array instances instead of tuple instances.


Chapter 5. Unordered Associative Containers

The more laws and order are made prominent,
The more thieves and robbers there will be.

The Way of Lao-tzu
LAO-TZU

Suppose that you've been asked to write the symbol table for a compiler. Whenever the code being compiled defines a new symbol, its name and its associated type information have to be stored in the symbol table. Whenever the code uses a name, the compiler has to find that name in the symbol table and dig out its properties. This is a typical job for an associative container: You have the value of a key, and you need to find the data associated with that key. With the current standard C++ library, you can do this with a map:

typedef std::string name;
struct type_data { type_id type; unsigned flags; };
std::map<name, type_data> sym_tab;

But compiler writers are speed freaks, and doing an O(logn) lookup, as map does, in a symbol table drives them nuts. So, after you show this to them and the screaming dies down, you rewrite your symbol table like this:

typedef std::string name;
struct type_data { type_id type; unsigned flags; };
std::tr1::unordered_map<name, type_data> sym_tab;

Now you're providing constant-time lookups, and the compiler guys are happy.[1]

[1] Well, they're as happy as compiler guys ever get. It's a tough job.


Section 5.1. Standardizing Hash Tables

5.1. Standardizing Hash Tables

One of the most commonly requested additions to the standard C++ library is hash tables. Properly used, they can provide significant speed improvements in searches. A 1995 proposal to add STL-style hash tables to the standard library was rejected because the target date for completion of the standard did not leave enough time for proper evaluation and adaptation of the proposed changes. Now that there's time, the TR1 library provides hash tables, under the names unordered_map, unordered_multimap, unordered_set, and unordered_multiset.[2] These template classes are defined in the headers <unordered_map> and <unordered_set>. In addition to these four containers, the TR1 library provides a template class named hash that provides the default hash functions for these containers.

[2] The more obvious names, hash_map, and so on, were rejected because they are already widely used for hash tables that are somewhat different from the hashed containers in TR1.

These containers don't quite fit into the existing set of container requirements, so TR1 provides a new set of requirements for what it formally refers to as "unordered associative containers." Don't let the name confuse you: Their requirements are slightly different from the requirements for associative containers, so the two kinds aren't quite interchangeable. We'll look at their differences in more detail a little later.

One of the biggest problems in designing a generic interface to a hash table is choosing the right set of parameters for tuning the operation of the resulting objects. With too few parameters, the template is too inflexible for broad use. With too many, it's too flexible, and it becomes difficult to know what it's really doing. TR1's unordered containers can be tuned at compile time by selecting suitable type arguments for hashing data values and for comparing data values for equality. They can be tuned at runtime by setting the maximum allowable load factor, which determines how many objects can be inserted in the container without forcing it to reshuffle them into more buckets, and by calling the member function rehash, which forces that reshuffling.


Section 5.2. Hash Tables

5.2. Hash Tables

A hash table stores elements in buckets. Each bucket can hold zero or more elements. The hash table chooses a bucket for an element, based on the hash value for that element. The hash value for an element is determined by passing that element to a hash function. If this is done well, a hash table can provide constant-time searches.

Example 5.1. Hash Table (contunord/hashtable.cpp)

#include <algorithm>
#include <array>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <limits>
#include <list>
using std::tr1::array;
using std::copy; using std::find;
using std::ostream_iterator;
using std::list;
using std::cout; using std::setw;
using std::numeric_limits;

typedef list <int> bucket;
typedef array <bucket, 5> table;

size_t hash (int i)
  { // return hash value for i
  return i;
  }

void show (const table& tbl)
  { // show contents of buckets in table
  for (int i = 0; i <tbl.size (); ++i)
    { // show contents of bucket i
    cout << "bucket " << setw (2) << i <<":";
    copy (tbl [i]. begin (), tbl [i]. end (),
      ostream_iterator <int >(cout,""));
    cout  <<  '\n';
    }
  }

void insert (table& tbl, int val)
  { // insert val into table
  size_t hash_val = hash (val) % tbl.size ();
  tbl [ hash_val ]. push_back (val);
  }

bool contains (const table& tbl, int val)
  { // return true if tbl contains val
  int hash_val = hash (val) % tbl.size ();
  bucket::const_iterator  first = tbl [ hash_val ]. begin ();
  bucket::const_iterator  last = tbl [ hash_val ]. end ();
  return find (first, last, val) != last;
  }

void report (const table& tbl, int val)
  { // report whether tbl contains val
  cout << "table"
    << (contains (tbl, val)? "contains"
       :"does not contain")
    << val << '\n';
  }

int main ()
  { // demonstrate simple hash table
  table tbl;
  insert (tbl, 3);
  insert (tbl, 195);
  insert (tbl, 5);
  insert (tbl, 6);
  insert (tbl, 55);
  insert (tbl, 1);
  insert (tbl, 33);
  insert (tbl, 40);
  show (tbl);
  report (tbl, 3);
  report (tbl, 4);
  return 0;
  }

This code stores integer values in a hash table with five buckets, each of which is an object of type std::list<int>. The hash function, hash, takes an argument of type int and simply converts it to a value of type size_t.[3] The function insert calls hash with the value to be inserted, reduces the result modulo the size of the container, and uses the result as an index to determine which linked list to append the value to. As you can see, the time it takes to insert a new element into this hash table does not depend on how may elements are already in the list. Thus, insertion into this table is O(1).

[3] Despite what some compilers may tell you, this conversion is well defined and meaningful. If you get a warning for this code, either complain to the compiler writer or add a cast.

Searching this table for a value is more complicated. The function contains calls hash with the target value, reduces the result modulo the size of the container, and uses the result as an index to determine which linked list to search. The function then calls the standard algorithm find to look for the target value in that linked list. In looking for the target value, find walks through the list's controlled sequence until it finds a matching value or reaches the end of the sequence.[4] Thus, the time needed to find an element is proportional to the number of elements in the linked list. That's not a problem if only a few elements are in each linked list, but with a fixed number of linked lists, as in this particular version of a hash table, the linked lists become proportionately longer as we add elements to the table. On average, each linked list will have n/M elements, where n is the number of elements in the table and M is the number of buckets. When n/M is large, the time needed to find an element is proportional to the number of elements in the table, so is much longer than the constant-time lookup that hash tables are capable of.

[4] The actual algorithm used in the unordered containers is more sophisticated than this, but it still degenerates into linear time when the buckets are over-filled.

The key to keeping hash table searches fast is to keep the number of elements in each bucket as low as is reasonable. Since the average number of elements in each bucket is n/M, this means that we need to keep that ratio low. To do this, as n increases, we also need to increase M. That is, we need to add more buckets to the table and redistribute the elements held in the table throughout the new set of buckets. This process, known as rehashing, is so important to maintaining the speed of hash tables that TR1 hash tables are automatically rehashed whenever the average number of elements in each bucket exceeds the table's load factor.


Section 5.3. Associative Containers and Unordered Containers

5.3. Associative Containers and Unordered Containers

The C++ standard defines four standard categories of container types: containers, reversible containers, sequence containers, and associative containers. If you're careful, these abstract categories allow you to design an application that can be implemented with one of several different container types, leaving you the flexibility to select the container to use later on, when you know more about the characteristics of the real-world data that the application will handle. If your application uses only operations defined for a particular container category, you can use any container type that satisfies the requirements for that category. For example, we saw in Chapter 4 that the TR1 template class array is a reversible container but not a sequence container. It can be used in place of a list, a vector, or a deque in any application that relies only on the operations defined for a reversible container.

TR1 adds a fifth container category. Unordered containers satisfy all the requirements for containers but do not support any of the six comparison operators.[5] Unordered containers are not reversible, so they also do not have the member functions rbegin and rend, which return reverse iterators. Other than that, unordered containers provide the same set of operations as associative containers. In addition, unordered containers have a set of operations for examining the contents of individual buckets and tuning the operation of the container.

[5] The reason is that the unordered containers are unordered. Deciding whether two unordered containers hold sets of equal elements is expensive, and it is not at all clear what it would mean for one unordered container to be less than another.


Section 5.4. Requirements for Unordered Containers

5.4. Requirements for Unordered Containers

5.4.1. Container Requirements

According to the definition in the C++ standard, a container must support the requirements set out in this section.

A container type X must provide the following nested type names:

  • X::value_type: the type of the objects held in the container.

  • X::reference: the type of an lvalue of X::value_type.

  • X::const_reference: the type of a const lvalue of X::value_type.

  • X::const_iterator: a constant iterator type whose value type is X::value_type. It can belong to any iterator category except output iterator.

  • X::iterator: an iterator type whose value type is X::value_type. It can belong to any iterator category except output iterator, and objects of type X::iterator must be convertible to type X::const_iterator.

  • X::difference_type: the same type as iterator_traits<X::iterator>::difference_type.

  • X::size_type: an unsigned integer type that can represent any non-negative value of X::difference_type.

The following expressions must be valid and must have the given meaning. Here, a and b are objects of type X, and r has type X&.

  • X();X u;: constructs an object with an empty controlled sequence.

  • X(a);X u(a); X u = a;: constructs an object that is a copy of a.

  • (&a)-> X();: the destructor destroys each object in the controlled sequence and frees any memory allocated by a.

  • a.begin(); a.end();:for a const object a, returns an iterator object of type X::const_iterator; otherwise, returns an iterator object of type X::iterator. The range [a.begin(), a.end()) consists of iterators that point at each of the objects in a.

  • a.swap(b);: swaps the contents of a and b.

  • r=a;: the function returns X&, replacing r's controlled sequence with a copy of b's controlled sequence.

  • a.size();: returns a value of type X::size_type that holds the number of objects in a's controlled sequence.

  • a.max_size();: returns a value of type X::size_type that holds the largest possible number of elements in a container of type X.

  • a.empty();: returns a value of type bool that holds the value of a.size() == 0.

    The following expressions must be valid and must have the given meaning:

  • a==b: returns a value that is convertible to bool, with the value true only if a.size() == b.size() and std::equal(a.begin(), a.end(), b.begin()).

  • a != b: returns a value that is convertible to bool and holds the value !(a == b).

  • a < b: returns a value convertible to bool and holds the value returned by the call std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end()). If this expression is used, then for two objects c and d of type X::value_type, the expression c<d must be defined and must be a total ordering relationship.

  • a>b: returns a value that is convertible to bool and holds the value b < a.

  • a<=b: returns a value that is convertible to bool and holds the value !(a>b).

  • a>=b: returns a value that is convertible to bool and holds the value !(a<b).

5.4.2. Unordered Container Requirements

According to the definition in TR1, an unordered associative container must meet all the requirements for a container, as described in Section 5.4.1, except for the equality and inequality operations at the end. In addition, unordered associative containers must meet the requirements in this section.

Unordered associative containers must provide the following nested type names:

  • key_type: the type of the container's keys.

  • key_equal: the type of the object used to compare keys for equality.

  • hasher: the type used to produce hash values.

  • local_iterator: an iterator type used to iterate within a bucket. The members of iterator_traits<local_iterator> must name the same types as the members of iterator.

  • const_ local_iterator: an iterator type used to iterate within a bucket. The members of iterator_traits<const_local_iterator> must name the same types as the members of const_iterator.

In the following lists, X is an unordered associative container type, a is an object of type X, b is an object of type X or const X, first and last are input iterators that point at objects of type X::value_type and [first, last) is a valid range, hf is an object of type X::hasher or const X::hasher, eq is an object of type X::key_equal or const X::key_equal, and n is a value of type X::size_type.

Unordered associative containers provide constructors that support the following code constructs.

  • X(n, hf, eq); X a(n, hf, eq); constructs an object with at least n buckets, holding no objects. The container will use a copy of hf to compute hash values and a copy of eq to compare keys. Its time complexity is O(n).

  • X(n, hf); X a(n, hf); constructs an object with at least n buckets, holding no objects. The container will use a copy of hf to compute hash values and key_equal() to compare keys. Its time complexity is O(n).

  • X(n); X a(n); constructs an object with at least n buckets, holding no objects. The container will use hasher() to compute hash values and key_equal() to compare keys. Its time complexity is O(n).

  • X(); X a; constructs an object with an unspecified number of buckets, holding no objects. The container will use hasher() to compute hash values and key_equal() to compare keys. Its time complexity is O(1).

  • X(first, last, n, hf, eq); X a(first, last, n, hf, eq); constructs an object with at least n buckets, holding no objects, then inserts the objects in the range [first, last) into the container. The container will use a copy of hf to compute hash values and a copy of eq to compare keys. Its average time complexity is O(N), where N is distance(first, last). Its worst-case time complexity is O(N2).

  • X(first, last, n, hf); X a(first, last, n, hf); constructs an object with at least n buckets, holding no objects, then inserts the objects in the range [first, last) into the container. The container will use a copy of hf to compute hash values and key_equal() to compare keys. Its average time complexity is O(N), where N is distance(first, last). Its worst-case time complexity is O(N2).

  • X(first, last, n); X a(first, last, n); constructs an object with at least n buckets, holding no objects, then inserts the objects in the range [first, last) into the container. The container will use hasher() to compute hash values and key_equal() to compare keys. Its average time complexity is O(N), where N is distance(first, last). Its worst-case time complexity is O(N2).

  • X(first, last); X a(first, last); constructs an object with an unspecified number of buckets, holding no objects, then inserts the objects in the range [first, last) into the container. The container will use hasher() to compute hash values and key_equal() to compare keys. Its average time complexity is O(N), where N is distance(first, last). Its worst-case time complexity is O(N2).

  • X(b); X a(b); constructs an object that is a copy of b, including copies of b's hash object, equality predicate, and maximum load factor. Its average time complexity is O(b.size()), and its worst-case time complexity is O(b.size()2).

  • a = b; replaces the contents of a with the contents of b, including copies of b's hash object, equality predicate, and maximum load factor. Its average time complexity is O(b.size()), and its worst-case time complexity is O(b.size()2).

The following functions insert single objects into an unordered associative container. If the container does not allow duplicate keys, the functions return an object of type pair<X::iterator, bool>. The iterator object points at the element that compares equal to the function's argument. The bool value indicates whether the object was newly insertedwhich happens only when there is no object equal to the argument in the containeror whether the object was already present. The object q is a valid, dereferenceable iterator that points at an element of a, and r is a valid, dereferenceable const iterator that points at an element of a. The average time complexity of these functions is O(1), and their worst-case time complexity is O(a.size()).

  • a.insert(t); inserts an object equal to t into a.

  • a.insert(q, t); inserts an object equal to t into a, The iterator q points at an element that might be close to the position where t belongs.

  • a.insert(r, t); inserts an object equal to t into a, The iterator r points at an element that might be close to the position where t belongs.

This function inserts multiple objects into an unordered associative container.

  • a.insert(i, j); the iterators i and j must not point at objects in a. The function returns void. It calls a.insert(t) for each of the objects pointed at by the iterators in the range [i, j).

The following functions remove objects from an unordered associative container. The objects q1 and q2 are objects of type X::iterator that point at elements in the container, and the objects r1 and r2 are objects of type X::const_iterator that point at elements of the container.

  • a.erase(k); the function returns a value of type X::size_type. It removes all elements whose key compares equal to the Key value k and returns the number of elements that were removed. Its average time complexity is O(a count(k)), and its worst-case time complexity is O(a.size()).

  • a.erase(q); a.erase(r); the first function returns an object of type X::iterator and the second function returns an object of type X:: const_iterator. The functions remove the element pointed at by q and r, respectively, and return an iterator object that points at the element that followed that element. Their average time complexity is O(1), and their worst-case time complexity is O(a.size()).

  • a.erase(q1, q2); a.erase(r1, r2); the first function returns an object of type X::iterator. The second function returns an object of type X::const_iterator. The functions remove the elements pointed at by the iterators in the range [q1, q2) and [r1, r2), respectively, and return an iterator object that points at the element that followed the erased elements. Their average time complexity is O(distance(q1,q2)) and O(distance(r1,r2)), respectively, and their worst-case time complexity is O(a.size()).

  • a.clear(); the function returns void. It removes all the elements from the container. Its time complexity is O(a.size()).

The following functions search an unordered associative container for objects that match a given key k:

  • b.find(k); for a const object b, returns an iterator object of type X::const_iterator;otherwise, returns an iterator object of type X ::iterator. The returned object points at an object in b whose key compares equal to the X::Key value k. If no such object exists, the returned object is equal to b.end(). Its average time complexity is O(1), and its worst-case time complexity is O(b.size()).

  • b.count(k); returns a value of type X::size_type, equal to the number of objects in b whose key compares equal to the X::Key value k. Its average time complexity is O(1), and its worst-case time complexity is O(b.size()).

  • b.equal_range(k); for a const object b, returns an object of type pair<X::const_iterator, X::const_iterator>; otherwise, returns an object of type pair<X::iterator, X::iterator>. The pair defines a range that contains all the objects in b whose key compares equal to the X::Key value k. If no such object exists, the function returns make_pair(b.end(), b.end()). Its average time complexity is O(b.count(k)), and its worst-case time complexity is O(b.size()).

The preceding member functions are all required for associative containers.[6] Unordered associative constainers provide additional member functions that support the following code constructs.

[6] The main difference between associative containers and unordered associative containers is in the time-complexity requirements. The complexity of inserting an object into an associative container and of searching an associative container is O(log n). As we've seen, in unordered associative containers, it is often O(1) but sometimes O(n).

  • b.hash_function() returns an object of type X::hasher that is a copy of b's hash object.

  • b.key_eq() returns an object of type X::key_equal that is a copy of b's equality predicate.

  • b.bucket_count() returns a value of type X::size_type that is the number of buckets in b.

  • b.max_bucket_count() returns a value of type X::size_type that is an upper bound on the number of buckets that b can contain.

  • b.bucket(key) returns a value of type X::size_type that is the index of the bucket where objects whose key is equal to key would be found.

  • b.bucket_size(n) returns a value of type X::size_type that is the number of objects in the bucket at index n. Its time complexity is O(M), where M is the number of objects in the bucket.

  • b.begin(n); b.end(n); for a const object b, returns an object of type X::const_local_iterator;otherwise, returns an object of type X::local_iterator. The range [b.begin(n), b.end(n)) contains all the objects in the nth bucket.

  • b.load_factor() returns a value of type float whose value is the average number of objects in each bucket.

  • b.max_load_factor() returns a value of type float whose value is the target load factor. See Section 5.10.

  • a.max_load_factor(z) sets the target load factor to the positive floating-point value z. See Section 5.10.

  • a.rehash(n) resizes the container so that it has at least n buckets and its load factor is less than or equal to its target load factor. See Section 5.10.

5.4.3. Exception Safety

The first rule of exception safety is: Don't write hash objects or equality predicates that throw exceptions. I can't imagine a reason for wanting to do that, but the TR1 specification doesn't prohibit it. It just doesn't promise much of anything if either of those functions throws an exception.

Here are the rules that unordered associative containers must follow with regard to exceptions.

  • The clear member function does not throw exceptions.

  • The erase member functions do not throw exceptions other than those thrown by the hash object or the equality predicate.

  • The insert member functions that insert one element have no effect if an exception is thrown during their execution other than by the hash object.

  • The swap function does not throw exceptions other than any exceptions thrown by the copy constructor or the copy assignment operator of the hash object or the predicate object.

  • The rehash function has no effect if an exception is thrown during its execution other than by the hash object or the equality predicate.


Section 5.5. The Headers <unordered_map> and <unordered_-set>

5.5. The Headers <unordered_map> and <unordered_-set>

The header <unordered_map> has the definitions for the two templates unordered_map and unorded_multimap and their corresponding swap functions.

namespace std {         // C++ Standard Library
 namespace tr1 {        // TR1 additions

    // TEMPLATE CLASS unordered_map
template <class Key, class Ty,
    class Hash = hash<Key>,
    class Pred = equal_to<Key>,
    class Alloc = allocator <pair < const Key, Ty > > >
      class unordered_map;

    // TEMPLATE CLASS unordered_multimap
template < class Key, class Ty,
    class Hash = hash <Key >,
    class Pred = equal_to <Key>,
    class Alloc = allocator <pair < const Key, Ty> > >
      class unordered_multimap;

    //TEMPLATE FUNCTIONS swap
template <class Key, class Ty,
  class Hash, class Pred, class Alloc>
void swap (
  unordered_map (Key, Ty, Hash, Pred, Alloc>& left,
  unordered_map (Key, Ty, Hash, Pred, Alloc>& right);
template <class Key, class Ty,
  class Hash, class Pred, class Alloc>
void swap (
  unordered_multimap (Key, Ty, Hash, Pred, Alloc>& left,
  unordered_multimap (Key, Ty, Hash, Pred, Alloc>& right);

} }

The header <unordered_set> has the definitions for the two templates unordered_set and unorded_multiset and their corresponding swap functions.

namespace std {         // C++ Standard Library
 namespace tr1 {        // TR1 additions

     // TEMPLATE CLASS unordered_set
template <class  Key,
    class Hash = hash<Key>,
    class Pred = equal_to<Key>,
    class Alloc = allocator <Key> >
      class unordered_set;

    // TEMPLATE CLASS unordered_multiset
template <class Key,
    class Hash = hash<Key>,
    class Pred = equal_to<Key>,
    class Alloc = allocator<Key> >
      class unordered_multiset;

    // TEMPLATE FUNCTIONS swap
template <class Key, class Hash, class Pred, class Alloc>
void swap (unordered_set (Key, Hash, Pred, Alloc >& left,
    unordered_set (Key, Hash, Pred, Alloc >& right);
template <class Key, class Hash, class Pred, class Alloc>
void swap (unordered_multiset (Key, Hash, Pred, Alloc >& left,
    unordered_multiset (Key, Hash, Pred, Alloc>& right);

} }

The full synopsis for each of the four unordered containers is rather lengthy and mostly repeats the things we looked at in Section 5.4, so instead of going through all their details,[7] we'll look at a summary of the functions that they have in common with their ordered counterparts in Section 5.9. We'll look at what the template parameters mean in Section 5.7, at the various constructors in Section 5.8, at rehashing in Section 5.10, and at how to tune a container in Section 5.11.

[7] You can look at the details in Appendix A.2 and Appendix A.3.


Section 5.6. The Class Template hash

5.6. The Class Template hash

The header <functional> defines the template class hash:

namespace std {
 namespace tr1 {
    // CLASS TEMPLATE hash
template<class Ty> struct hash
  : unary_function<Ty, size_t>
  { // function object to compute hash values
  size_t operator()(Ty val) const;
  };
} }

The template class hash<Ty> describes a callable type whose function call operator takes one argument of type Ty and returns a value of type std::size_t. Its function call operator shall not throw any exceptions and shall return the same value when called with equal arguments.

The template class shall be defined in such a way that it can be instantiated with the following types:

  • bool

  • Integer types: char, signed char, unsigned char, short, unsigned short, int, unsigned int, long, unsigned long, _-Longlong, _ULonglong

  • Floating-point types: float, double, long double

  • Pointer types

  • Strings: std::string, std::wstring

Objects of type hash<Ty> provide the default hash functions for the unordered containers. If the type of your container's key is not one of the types required for hash, you can write your own specialization.

Example 5.2. Specializing hash (contunord/hash.cpp)

#include <functional>
#include <iostream>
#include <string>
#include <iterator>
#include <vector>
using std::tr1::hash;
using std::cout; using std::string;
using std::vector; using std::iterator_traits;

template <class InIt>
void show_hashes (InIt first, InIt last)
  { // demonstrate use of hash<Ty>
  typedef typename
    iterator_traits <InIt>:: value_type type;
  hash <type> hasher;
  while (first != last)
    cout << hasher (*first++) << '';
  cout << '\n';
  }

struct coord
  { // two-dimensional integer coordinates
  int x, y;
  };

namespace std {
namespace tr1 { // put specialization in std::tr1
template  <>
struct hash <coord>
  { // template specialization for struct coord
  std::size_t operator ()(const coord & val) const
    { // return hash value for val
    hash <int> make_hash;
    return make_hash (val .x) + make_hash (val .y);
    }
  };
}}

#define SIZE (arr) (sizeof (arr) / sizeof (* arr))

int main ()
  { // demonstrate use and specialization of hash<Ty>
  int data [] = { 1, 2, 3, 4, 5 };
  show_hashes (data, data + SIZE (data));

  char * text [] = { "1", "2", "3", "4", "5" };
  vector <string> strings (text,  text + SIZE (text));
  show_hashes (strings.begin (),   strings.end ());

  coord points [] = { { 0, 0 }, { 0, 1 }, { 1, 0 },
    { 1, 1 }, { 2, 2 } };
  show_hashes (points,   points + SIZE (points));
  return  0;
  }


Section 5.7. Instantiating the Unordered Containers

5.7. Instantiating the Unordered Containers

As we've seen, the template classes unordered_set and unordered_multiset take a single template parameter, referred to as the Key type, that gives the type of the objects to be held in the container. They both take additional template parameters that have default values, so you often won't have to write them out.

Similarly, the template classes unordered_map and unordered_multimap take two template parameters: a Key type that gives the type of the objects to be used as keys and an associated type Ty that gives the type of the objects that will be associated with those keys. They also take the same list of additional template parameters with default values that unordered_set and unordered_multiset take.

The Key type is used to store and find objects in the unordered associative containers. In order to do this, it must be possible to compute hash values for objects of type Key. By default, the containers all use the callable type std::tr1::hash<Key>. If that type is valid for the Key type, either because it's supported by the implementation or because your code supplies a specialization for your key type, the default will work. Otherwise, you need to provide your own type for computing hash values. You do that by passing the name of your type as the next argument in the template's parameter list:

struct MyKey
{
// whatever...
};

struct MyHash
{
size_t operator ()(myKey key) const;
};

  // uses hash<MyKey>:
std::tr1::unordered_set <MyKey> set1;
  // uses MyHash:
std::tr1::unordered_set <MyKey, MyHash> set2;

The containers also use std::equal_to<Key> to decide whether two key values are equal. That template, in turn, returns the result of applying operator== to the key objects. So if you have an operator== for your key types, or if you have a specialization of std::equal_to for your key types, the default equality predicate will work. Otherwise, you'll need to provide your own predicate type:

namespace std { // put specialization in std
template <>
struct equal_to <MyKey>:
  public binary_function <MyKey, MyKey, bool>
{
bool operator ()(const MyKey&, const MyKey&) const;
};
}

struct MyEq
{
bool operator ()(const MyKey&, const MyKey&) const;
};

   // uses equal_to<MyKey>:
std::tr1::unordered_set <MyKey, MyHash> set3;
   // uses MyEq:
std::tr1::unordered_set <MyKey, MyHash, MyEq> set4;

Finally, as with all the other containers, you can pass a final template parameter that gives the type of the allocator for the container to use when it needs to allocate memory.

In all these cases, the container will use the default constructor to create the objects that it uses for hashing, comparing, and allocating. If your type needs something more than default construction, in addition to naming the type as a template parameter, you must pass a suitably constructed object to the container's constructor. The container will make copies of those objects and use them for hashing and comparing.


Section 5.8. Constructors

5.8. Constructors

You can specify the initial contents of an unordered associative container in three ways. You can provide no initial contents, you can provide another container to copy, and you can provide a range of iterators that point at initial values. We've seen these three forms of constructor in Section 5.4.1 and Section 5.4.2. They are used like this:

unordered_set<int> u0;                       //no initialization
unordered_set<int> u1(u0);                  //copy initialization
unordered_set<int> u2(u1.begin(), u1.end());
                                              //range initialization

Of course, using another container to provide a range is simply a handy example. You can use any range defined by a pair of iterators whose associated value_type is the same as the type held by the container.

The first and the third forms of constructor can also be used with additional arguments. You can pass a value of type X::hasher if your hash object needs initialization. If you pass an X::hasher object, you can also pass a value of type X::key_equal if your equality predicate needs initialization. Finally, if you've passed both of these, you can also pass an object of type X::allocator if your allocator needs initialization.


Section 5.9. Container Operations

5.9. Container Operations

Just as with ordered containers, you can insert a value t by calling the member function container.insert(t). You can insert with a hint by using insert(q, t), where q is an iterator into the container. You can insert a sequence of values with insert(i, j), where i and j are iterators that designate a sequence of values.

To remove elements, unordered containers provide the usual clear and erase member functions. You can call erase with a value to remove all elements whose key compares equal to that value. You can also call it with an iterator that designates the element to be removed. Finally, you can call it with a pair of iterators that designates a range of elements within the container to be removed.

To search for elements, unordered containers provide the member functions find, count, and equal_range. Each of them takes a key value to search for. The member function find returns an iterator that points to an element whose key compares equal to the key value, or an iterator equal to end() if no such element exists. The member function count returns the number of elements whose keys compare equal to the key value. The member function equal_range returns a pair of iterators that designates a range of elements within the container, all of whose keys compare equal to the key value.[8]

[8] This requirement means that the simple implementation of a hash table in the example in Section 5.2 can't be used as an unordered container. It doesn't group elements that compare equal together, so there might not be a valid range that holds all elements that compare equal to a given key and no others.

If you stick to these operations, you can write code that works with both the associative containers and the unordered associative containers. For example, the following program[9] works when it's implemented with either a std::map or a std::tr1::unordered_map.

[9] Based on an example in The C++ Standard Library [Jos99, 209211].

Example 5.3. Basic Operations (contunord/basics.cpp)

#include <unordered_map>
#include <iostream>
#include <ostream>
#include <iomanip>
#include <string>
#include <utility>
#include <algorithm>
#include <iterator>
#include <functional>
using std::tr1::unordered_multimap;
using std::string; using std::make_pair; using std::pair;
using std::setw; using std::setfill;
using std::copy; using std::cout;
using std::basic_ostream;   using std::ostream_iterator;
using std::ios_base; using std::ios;
using std::unary_function;

typedef unordered_multimap <string, string> dictionary;
typedef dictionary::value_type element;

static const char * pairs [] =
  { // English/German word pairs
  "day",      "Tag",
  "strange",  "fremd",
  "car",      "Auto",
  "smart",    "elegant",
  "trait",    "Merkmal",
  "strange",  "seltsam",
  "smart",    "raffiniert",
  "smart",    "klug",
  "clever",   "raffiniert",
  0,            0
  };

namespace std  { // add inserter to namespace std
template  <class Elem, class Traits>
basic_ostream <Elem, Traits>&  operator <<(
  basic_ostream <Elem, Traits>& str, const element& elt)
  { // insert element into stream and restore flags
  ios_base::fmtflags flags = str.flags ();
  str.setf (ios::left, ios::adjustfield);
  str << '' << setw (10) << elt.first << elt.second;
  str.flags (flags);
  return str;
  }
}

template <class InIt, class OutIt, class Pred>
OutIt copy_if (InIt  first, InIt last, OutIt dest, Pred pr)
  { // copy elements for which pr(*first) is true
  for (; first != last; ++ first, ++ dest)
    if (pr (* first))
      * dest = * first;
  return  dest;
  }

struct  equals
  : unary_function <element, bool>
  { // callable type that matches second object in pair to string
  equals (const string& s) : str (s) {}
  bool operator ()(const element& elt) const
    { // return true for match
    return elt.second ==  str;
    }
private :
  string str;
  };

int main ()
  { // demonstrate use of unordered_multimap
  dictionary  dict;

    // initialize:
  const char ** cur = pairs;
  while (cur [0])
    { // add initial entries
    dict.insert (make_pair (cur [0],  cur [1]));
    cur +=  2;
    }

    // print out all elements
  ostream_iterator <element> output (cout, "\n");
  cout << make_pair (" English ", "German") << '\n';
  cout << setfill (' - ') << setw (20) << ""
    << setfill ('') <<   '\n';
  copy (dict.begin (), dict.end (),  output);

    // print out all values for key "smart"
  string key (" smart ");
  cout << '\n' << key << ":\n";
  copy (dict.lower_bound (key), dict.upper_bound (key),
    output);
    // print out all keys for value "raffiniert"
  string value (" raffiniert ");
  cout <<'\n' << value << ":\n";
  copy_if (dict.begin (), dict.end (),
    output,  equals (value));
  return 0;
  }


Section 5.10. Load Factors and Rehashing

5.10. Load Factors and Rehashing

We saw earlier that it's important to keep the average number of objects per bucket down if we want fast searches. In fact, there are some formalisms for talking about that. A hash table's load factor is the average number of objects per bucket. When a hash table's load factor is less than its target load factor, inserting another object won't trigger a rehash. You can get the hash table's current load factor by calling the member function load_factor(). You can get the table's target load factor by calling the member function max_load_factor(), and you can set the table's target load factor by calling max_load_factor(z), where z is the new value for the load factor.

The member function rehash(n) sets the number of buckets to at least n but large enough so that the load factor is less than the target load factor and then redistributes the hash table's objects into the new set of buckets. This usually reduces the number of objects in each bucket, which, in turn, improves search performance.

You won't ordinarily have to call rehash, though, because the container does it for you when the load factor gets too high. Technically, the requirement goes the other way around: as long as the load factor is less than the maximum load factor, insertions don't invalidate iterators. This means that objects can't be moved to other buckets, which in turn means that the table can't be rehashed. There is no requirement to rehash when the load factor gets too large, just a caution that rehashing might happen. That's a careful way of allowing incremental rehashing, which gradually increases the number of buckets in the table and moves some elements into new buckets on each insertion, rather than doing everything at once. That distributes the rehashing work over several insertions, which can improve responsiveness in real-time systems. If you've done a bunch of insertions and you're not going to do any more, it's a good idea to call rehash to make sure that rehashing has been completed.

Example 5.4. Load Factors and Rehashing (contunord/rehash.cpp)

#include <unordered_set>
#include <iostream>
using std::tr1::unordered_set;
using std::cout;

typedef unordered_set <int> iset;

static void show_details (const iset& set)
  { // show container properties
  cout << "load factor: " << set.load_factor ()
    << " target load factor: " << set.max_load_factor()
    << " buckets: " << set.bucket_count() << '\n';
  }

int main ()
  { // show growth pattern
  iset  set;
  show_details (set);
  int i;
  for (i = 0; i < 20; ++ i)
    set.insert (i);
  show_details (set);
  for (; i < 40; ++ i)
    set.insert (i);
  show_details (set);
  for (; i < 60; ++ i)
    set.insert (i);
  show_details (set);
  set.max_load_factor (2.0);
  show_details (set);
  set.rehash (10);
  show_details (set);
  set.rehash (30);
  show_details (set);
  return  0;
  }


Section 5.11. Tuning

5.11. Tuning

Tweaking the hash table's load factor can create a better distribution of objects among the buckets, but it won't help if your hash function isn't doing a good job. This isn't the place to talk about the details of good hash functionsthat's a large topic in itself. When you're storing data in a hash table, what you need to know is how well the hash function distributes the data that you have. You can look at the distribution with the member functions bucket_count(), which tells you how many buckets the hash table has; bucket_size(n), which tells you how many objects are in the nth bucket; and with the member functions begin(n) and end(n), which return iterators that you can use to look at the objects in the nth bucket. If your hash table isn't getting the performance you expect, this information can point you to the culprit. You may need to replace the hash function.

Example 5.5. Tuning a Hash Table (contunord/tuning.cpp)

#include <unordered_set>
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <iterator>
using std::cout; using std::setw;
using std::copy; using std::ostream_iterator;

typedef std::tr1::unordered_set <int> iset;
typedef iset::value_type elt;

static  void show_buckets (const iset& set)
  { // show details of buckets in set
  cout << setw (3) << set.size () << "elements,"
    << setw (3) << set.bucket_count () << "buckets,"
    << "load factor" << set.load_factor () << ".\n";
  for (int i = 0; i < set.bucket_count (); ++ i)
    cout << i << ':' << set.bucket_size (i) << "";
  cout << '\n';
  ostream_iterator <elt> output (cout, "");
  for (int i = 0; i <set.bucket_count (); ++i)
    { // show contents of bucket i
    cout << setw (3) << i << ":";
    copy (set.begin (i), set .end (i), output);
    cout << '\n';
    }
  }

int main ()
  { // demonstrate use of bucket functions
  iset  set;
  for (int i = 0; i <100; ++i)
    set.insert (i);
  show_buckets (set);
  return  0;
  }


Further Reading

  • The Art of Computer Programming [Knu98b, 513559] has the usual encyclopedic discussion of hashing.

  • Introduction to Algorithms [CLR90, 219243] has a more approachable discussion.


Exercises

Exercise 1

For each of the following errors, write a simple test case containing the error, and try to compile it. In the error messages, look for the key words that relate to the error in the code.

  1. Attempting to create an unordered container that holds an object type with no specialization of std::tr1::hash.

  2. Attempting to create an unordered container that holds an object type with no specialization of std::equal_to and no operator==.

Exercise 2

Define a struct named elt that holds a value of type unsigned int, and write a specialization of std::tr1::hash whose function call operator computes hash values for elt by returning twice the object's stored value. Create an object of type std::tr1::unordered_set<elt>, put a dozen or so objects of type elt into it, and examine the distribution of values in the buckets.

Exercise 3

Q1:

Change the specialization of std::tr1::hash in the previous exercise by adding a constructor that takes a value of type int, with a default value of 2, and stores it in the object. Change the function call operator to return that stored value times the value stored in the elt object.

  • Create an object of type std::tr1::unordered_set<elt>, and pass an object of type std::tr1::hash<elt> created with the default constructor to its constructor. Put a dozen or so objects of type elt into it, and examine the distribution of the values in the buckets.

  • Create an object of type hash<elt>, initialized with the value 3, and an object of type std::tr1::unordered_set<elt>, initialized with a size and the newly created hash<elt> object. Put a dozen or so objects of type elt into it, and examine the distribution of the values in the buckets.

  • Try the same thing again, with the hash<elt> object initialized with the value 4.

  • Try the same thing again, with the hash<elt> object initialized with the value 0.

Exercise 4

Q1:

Change the specialization of std::tr1::hash in the previous exercise so that it returns the remainder when the value stored in the elt object is divided by 4. Put a dozen or so objects of type elt into it, and examine the distribution of the values in the buckets.


Part III: Call Wrappers

    Chapter 6. Call Wrapper Basics

    Chapter 7. The mem_fn Function Template

    Chapter 8. The reference_wrapper Class Template

    Chapter 9. The function Class Template

    Chapter 10. The bind Function Template


Chapter 6. Call Wrapper Basics

"The name of the song is called 'Haddocks' Eyes.'"

"Oh, that's the name of the song, is it?" Alice said, trying to feel interested.

"No, you don't understand," the Knight said, looking a little vexed. "That's what the name is called. The name really is 'The Aged Aged Man.'"

"Then I ought to have said 'That's what the song is called' ?" Alice corrected herself.

"No, you oughtn't: that's quite another thing! The song is called 'Ways and Means': but that's only what it's called, you know!"

"Well, what is the song, then?" said Alice, who was by this time completely bewildered.

"I was coming to that," the Knight said. "The song really is 'A-sitting On A Gate': and the tune's my own invention."

Through the Looking Glass
LEWIS CARROLL

Back in Chapter 3, we looked briefly at callable types, which are most commonly used to create objects with function call operators that can be passed to algorithms that need to make decisions involving the sequence element they're currently looking at. That is, the function call operator is used just like a function: The algorithm calls it with the current element or a pair of elements, and the function call operator then returns a value that the algorithm uses. In fact, function pointers are callable types. However, it's often better to use an object with a function call operator instead of a function pointer, because the compiler can generate inline code for the function call operator but usually can't generate inline code for the function that a function pointer points at. Callable objects are also more flexible than function pointers, because different objects of the same type can hold different data values for use by the function call operator.[1]

[1] So, a less_than_value object can hold the value that you want to compare to; a less_-than_three function always compares against the same value.

TR1 introduces four new class templates that can be used to create function objects. These templates are defined in the header <functional>. Two of these class templatesreference_wrapper (discussed in Chapter 8) and function (discussed in Chapter 9)can be used directly. The names and template argument types of the other two class templates are unspecified; objects of these types are created by calling the function templates mem_fn (discussed in Chapter 7) and bind (discussed in Chapter 10). In addition, the library provides two function templatesref and creffor creating objects whose types are specializations of the template reference_wrapper. Finally, the library provides a template named result_of (discussed in Section 6.4) that can be used to determine the return type of a call expression.


Section 6.1. Terminology

6.1. Terminology

Discussions of function objects are often confusing because the same words are used to mean different things. The documentation for the TR1 library introduces several terms of art for discussing and specifying what function objects do. First, a callable type is a pointer to function, a pointer to member function, a pointer to member data, [2] or a class type whose objects can appear to the left of a function call operator.[3]

[2] You might be surprised to see pointer to member data in this list; a pointer to member data is obviously not like a function. But the new function template mem_fn can create objects that bind a pointer to member data and a pointer or reference to an object; this uses the same function call syntax as an actual function call, so pointers to member data are callable types.

[3] This wording may seem a little convoluted, but it was carefully written to not require that the type define a function call operator. That leaves open the possibility that a function object can provide a conversion operator that returns a pointer to function; when such an object appears to the left of a function call operator, the compiler uses the conversion function to get the function pointer and then calls the function it points to.

For example, given a class C, the following are all callable types:

typedef float (*call0)(float);     // pointer to function
typedef long (C::*call1)();        // pointer to member function
typedef int C::*call2;             // pointer to member data

In addition, if the class C has a member operator() or a conversion to a pointer to function, the class is a callable type:

typedef C call3;     // function call operator

Naturally, a callable object is an object of a callable type. If we fill in the definition of the class C like this:

    class C
      {
    public:
      C(int i0) : i(i0) {}
      long get () const { return i; }
      int i;
      void operator ()(int ii) { i = ii; }
      };

we can define and initialize four callable objects like this:
    call0 c0 = cosf;             // pointer to  cosf in standard library
    call1 c1 = &C::get;          // pointer to C::get member function
    call2 c2 = &C::i;            // pointer to C::i data member
    call3 c3;                    // object of type C

A call wrapper type holds a callable object and supports a call operation that calls through that object; a call wrapper is an object of a call wrapper type. A target object is the callable object held by a call wrapper.

Example 6.1. Call Wrapper (funobjover/callwrap.cpp)

#include <iostream>
#include <math .h>
using std::cout;

class wrapper
  { // simple call wrapper type
  typedef float(*fp)(float);
public:
  wrapper(fp ptr) : fptr(ptr) {}
  float operator()(float arg)
    { // call operation; forwards to target object
    return fptr(arg);
    }
private:
  fp fptr;                        // target object
  };

int main()
  { // demonstrate use of call wrapper
  wrapper  wrap (cosf);           // call wrapper
  cout << "cosf (1.0) is " << cosf (1.0) << '\n';
  cout << "wrap (1.0) is " << wrap (1.0) << '\n';
  return 0;
  };

Every call wrapper can be copy constructed. In addition, if a call wrapper has an assignment operator, and if its copy constructor and assignment operator do not throw exceptions, it is a simple call wrapper. If it can be called with a list of arguments that are all lvalues, it is a forwarding call wrapper.[4]

[4] Writing forwarding call wrappers as templates is a tricky problem. Some lvalues are modifiable, and some aren't. Modifiable lvalues have to be passed by reference, so that the called function can modify them. Nonmodifiable lvalues have to be passed by value or by reference to const, so that the called function can't modify them. At present, nobody has figured out how to detect which is which, so a function call operator that's written as a template can't simply forward its arguments to its target object.


Section 6.2. Requirements for Call Wrapper Types

6.2. Requirements for Call Wrapper Types

TR1 defines some additional terms that are used to describe requirements for callable types.

First, INVOKE(fn, t1, t2, ..., tN) describes the effect of calling a callable object fn with the arguments t1, t2, ..., tN. Naturally, the effect depends on the type of the callable object. INVOKE is defined as follows:

  1. (t1.*fn)(t2, ..., tN) when fn is a pointer to a member function of a class T and t1 is an object of type T or a reference to an object of type T or a reference to an object of a type derived from T

  2. ((*t1).*fn)(t2, ..., tN) when fn is a pointer to a member function of a class T and t1 is not one of the types described in the previous item

  3. t1.*fn when fn is a pointer to member data of a class T and t1 is an object of type T or a reference to an object of type T or a reference to an object of a type derived from T

  4. (*t1).*fn when fn is a pointer to member data of a class T and t1 is not one of the types described in the previous item

  5. fn(t1, t2, ..., tN) in all other cases

What this amounts to is that when the callable object is an ordinary function or a pointer to an ordinary function, INVOKE means to call that function, passing the rest of the arguments to the function call. When the callable object is a pointer to member, the next argument refers to the object that it should be applied to. That argument is the object itself, a reference to the object, a pointer to the object, or some kind of smart pointer that points to the object. The rest of the arguments are passed to the function call.

Second, INVOKE_R(fn, t1, t2, ..., tN, Ret) describes the effect of calling a callable object fn with an explicit return type, Ret. It is defined as INVOKE(fn, t1, t2, ..., tN) implicitly converted to Ret.[5]

[5] In the TR, this metafunction is named INVOKE; although I'm one of the people responsible for this name overloading, I've now concluded that it's too clever and shouldn't be used.

Third, some call wrapper types have a weak result type; this means that they have a nested member named result_type that names a type determined from the call wrapper's target type, Ty.

  • If Ty is a function, reference to function, pointer to function, or pointer to member function, result_type is a synonym for the return type of Ty

  • If Ty is a class type with a member type named result_type, result_type is a synonym for Ty::result_type

  • Otherwise, result_type is not defined[6]

    [6] That is, not defined as a consequence of having a weak result type. Some call wrapper types have a weak result type in certain circumstances, have a specific type named result_type

A few examples will help clarify what this rather dense text means:

struct base {
void f();
int g(double);
int h(double,double);
};
struct derived : base {
};

base b;
derived d;
base& br = d;

With these definitions, rule 1 gives the following meanings to these uses of INVOKE .

Phrase | Meaning
INVOKE (&base::f, b) | (b.*f)()
INVOKE (&base::g, d, 1.0) | (d.*f)(1.0)
INVOKE (&base::h, br, 1.0, 2.0) | (br.*f)(1.0, 2.0)

That is, the pointer to member function is called on the object or reference named by t1:

derived *dp = new derived;
base *bp = dp;
shared_ptr<base> sp(bp);

With these additional definitions, rule 2 gives the following meanings to these uses of ( INVOKE):

Phrase | Meaning
INVOKE (&base::f, bp) | ((*bp).*f)()
INVOKE (&base::g, dp, 1.0) | ((*dp).*f)(1.0)
INVOKE (&base::h, sp, 1.0, 2.0) | ((*sp).*f)(1.0, 2.0)

That is, the pointer to member function is called on the object that the argument t1 points to. Since it uniformly dereferences that argument, the rule works for any type whose operator* returns a reference to a suitable object. In particular, the rule works for shared_ptr objects.

Rules 3 and 4 give similar meanings to INVOKE uses that apply pointers to member data:

void func(base&);
struct fun_obj {
void operator()() const;
bool operator()(int) const;
};
fun_obj obj;

With these additional definitions, rule 5 gives the following meanings to these uses of INVOKE:

Phrase | Meaning
INVOKE (func, d) | func(d)
INVOKE (obj) | obj()
INVOKE (obj, 3) | obj(3)


Section 6.3. Header <functional> Synopsis

6.3. Header <functional> Synopsis

The TR1 library adds the following templates to the header <functional>:

namespace std {
  namespace tr1 {

    // CALLABLE OBJECT RETURN TYPES
template <class Ty> struct  result_of;
    // REFERENCE WRAPPERS
template <class Ty>
  struct reference_wrapper;
template <class Ty>
  reference_wrapper<const Ty> cref(const Ty&);
template <class Ty>
  reference_wrapper<const Ty> cref(reference_wrapper<Ty>);
template <class Ty>
  reference_wrapper<Ty> ref(Ty&);
template <class Ty>
  reference_wrapper<Ty> ref(reference_wrapper<Ty>);

    // FUNCTION OBJECT WRAPPERS
class bad_function_call;
template<class Fty>
  class function;
template<class Fty>
  bool operator==(const function<Fty>&, null_ptr_type npc);
template<class Fty>
  bool operator==(null_ptr_type npc, const function<Fty>&);
template<class Fty>
  bool operator!=(const function<Fty>&, null_ptr_type npc);
template<class Fty>
  bool operator!=(null_ptr_type npc, const function <Fty>&);
template<class Fty>
  void swap(function<Fty>& f1, function<Fty>& f2);

    // ENHANCED MEMBER POINTER ADAPTER
template <class Ret, class Ty>
  unspecified mem_fn(Ret Ty::*);

    // ENHANCED BINDERS
template <class Fty,
    class T1, class T2, ..., class TN>
  unspecified bind(Fty, T1, T2, ..., TN);
template <class Ret, class Fty,
    class T1, class T2, ..., class TN>
  unspecified bind(Fty, T1, T2, ..., TN);
template <class R, class Ty,
    class T1, class T2, ..., class TN>
  unspecified bind(R Ty::*, T1, T2, ..., TN);
template <class Ret, class R, class Ty,
    class T1, class T2, ..., class TN>
  unspecified bind(R Ty::*, T1, T2, ..., TN);
template <class Ty> struct is_placeholder;
template <class Ty> struct is_bind_expression;
  namespace placeholders {
    extern unspecified _1;
    } // placeholders

} };

Callable object return types are discussed in Section 6.4; reference wrappers in Chapter 8; function object wrappers in Chapter 9; the enhanced member pointer adapter in Chapter 7; and enhanced binders in Chapter 10.


Section 6.4. The result_of Class Template

6.4. The result_of Class Template

template<class Ty> struct result_of {
  typedef T1 type;
  };

One problem that you often run into when writing call wrapper types is that you need to figure out the return type of a call to the target object. The target object, as we've seen, can be a pointer to function, a pointer to a member function, a pointer to member data, or an object with at least one function call operator. The type of the value you get from a pointer to member data depends on the type of the object that it's being applied to, [7] and the return type of an overloaded function call operator can depend on which overload is selected, which, in turn, depends on the arguments that are passed to it. Having to figure out the return type of one of these objects is tedious and error prone. TR1 provides a template, result_of, that gives you a uniform way of getting this information.

[7] That is, its const and volatile qualifiers are determined in part by the type of the object.

The template takes a single type argument that contains the type of a callable object and the list of argument types. This is done by using the syntax of a function type (discussed in Chapter 9). That is, the template argument consists of the callable type followed by a left parenthesis followed by a possibly empty list of argument types followed by a right parenthesis.[8] (As we'll see later, a pointer to member is treated as a function whose first argument designates the object that the member function will be applied to, so the argument list for a pointer to member always has at least one argument type.) The resulting template specialization has a nested type named type that is a synonym for the return type of the template argument.

[8] Since it does not describe a function returning the callable type, the template argument is not, in fact, a function type. The compiler doesn't care, though, so smuggling in the callable type in the guise of a return type works.

Example 6.2. Class Template result_of (funobjover/resultof.cpp)

#include <functional>
#include <math .h>
#include <iostream>
#include <typeinfo>
using std::tr1::result_of;
using std::ostream; using std::cout;

class C
  { // sample class
public:
  C(int i0) : i(i0) {}
  long get() const { return i; }
  int i;
  void operator()(int ii) { i = ii; }
  typedef void result_type;
  };

template <class Fty,class Arg>
void show_return(Fty fun,Arg arg)
  {   // show return type of fun(arg)
  typedef typename result_of<Fty(Arg)>::type ret;
  cout << "Return type of " << typeid(Fty).name()
    << " when called with " << typeid(Arg).name()
    << " is " << typeid(ret).name() << '\n';
  }

int main()
  { // demonstrate class template result_of
  C c(1);
  C *cp = &c;
  const C *ccp = &c;
  show_return(cosf, 1.0);                // cosf(float) returns float
  show_return(&C::get, cp);              // C::get() returns long
  show_return(&C::i, ccp);               // C::ihas type const int
  show_return(c, 3);                     // C() returns void
  return 0;
  }

Depending on which compiler you use, you may have to decipher the type names produced by this program; some compilers give rather cryptic names. In any event, the four calls to show_return should all display the correct return types for the four call wrapper types.

More formally, the nested type named by result_of<F(T1,T2,...,TN)>::type is the return type of the expression f(t1,t2,...,tN), where f is an object of type F, and t1, t2, ..., tN are objects of type T1, T2, ..., TN, respectively. When any of the types Ti is a reference, the corresponding object ti will be an lvalue; otherwise, ti will be an rvalue.

Most of the time when you need to use this template you'll be inside the code of some other template, and the callable type will come in as a template argument. Occasionally, though, you may have to write out the declaration of the callable type and the argument list yourself. This can be confusing, because some callable types have their own argument type list, and you end up with two lists. If you have to write out the full argument list in a case like that, use a typedef for the callable type:[9]

[9] If you really want to know, when you have a pointer to function, the argument type list goes immediately after the *:result_of<int(*(float))(double)>::type.

typedef int (*func)(doubl);            // func is the callable type
result_of<func(float)>::type           // ...

Unfortunately, result_of can't be implemented in portable C++ code. It needs help from the compiler to figure out the return types of function call operators, because there is no way to examine the declaration of the function call operator to determine its return type.[10] Since it is not part of the C++ standard, TR1 ought to be implementable without that sort of help, so it has a list of rules that the implementation should follow if it can't get the return type exactly right. Since TR1 permits this behavior, portable code that uses TR1 should not rely on getting the exact type but should assume that these rules will be applied.

[10] This also means that you can't use result_of to determine which of several overloaded versions of operator() will be called.

For a callable type F and a set of argument types T1, T2, ..., TN, the type result_of<F(T1, T2, ..., TN)>::type is determined as follows.

  • If the type F is a function object defined in the standard library, the nested type type is a synonym for the return type of the call f(t1, t2, ..., tN).

  • If the type F is a pointer to function or a function type, the nested type type is a synonym for its return type.

  • If the type F is a pointer to member function, the nested type type is a synonym for its return type.

  • If the type F is a pointer to data member of a class Ty, the nested type type is a synonym for cv R&, where R is the declared type of F, and cv represents the const and volatile qualifiers of the Ty object referred to by t1.

  • If the type F is a class that has a member named result_type that names a type, the nested type type is a synonym for F::result_-type.[11]

    [11] This requirement is not in TR1, so an implementation that conforms to the TR1 spec-ification does not have to satisfy it. It was accidentally left out and will be added in the future.

  • If the type F is a class that does not have a member named result_-type or that has a member named result_type that does not name a type:

    - If the argument list is empty (N is 0) the nested type type is a synonym for void.

    - Otherwise, the nested type type is a synonym for typename F::result<F(T1, T2, ..., TN)>::type.[12]

    [12] That is, if F defines a nested template named result, result_of uses that template; if F doesn't define that template, it's an error.

  • Otherwise, the program is ill-formed.

These rules are complicated because they try to accommodate existing practice. For the most part, you shouldn't need this much detail. For ordinary functions and pointers to members, result_of gets the return type right. When you write a class with a function call operator, include a member typedef named result_type that names the return type of the function call operator. Don't overload function call operators.


Section 6.5. Interoperating with Existing Function Objects

6.5. Interoperating with Existing Function Objects

The function object types in the standard C++ library take one or two arguments that are passed by value. The types of these arguments and the return type of a function object's operator() are specified by template arguments that are passed to the template that defines the type of the function object. For example:

#include <functional>

std::plus<int> adder;
std::equal_to<int> comparator;

Here, the object adder has a function call operator that takes two arguments of type int and returns int. The template argument defines all three of those types. Similarly, the object comparator has a function call operator that takes two arguments of type int, specified by the template argument. The return type of the function call operator defined by the template std::equal_to, however, is always bool.

When you call the function call operators for either of these objects, the arguments you pass will be converted to the type that you gave as the template argument; in these two examples, that type is int:

adder(1.1,1.2);          // returns 2
comparator(1.1,1.2);     // returns true

In the TR1 library, the class template function works the same way: The types of the arguments to the function call operator are determined by the template argument used to instantiate function. The other three function object types, however, use a different scheme. Their function call operator is itself a template; its argument types are determined by the types that you call it with. And, as I mentioned earlier, its return type is often determined with the template result_of rather than an explicit template argument.

All the function object types in the standard C++ library describe their argument types and their return type with nested typedefs. Single-argument types have a nested type named argument_type, and two-argument types have two nested types: first_argument_type and second_argument_type. They all have a nested type named result_type. These types are defined by deriving from one of the templates unary_function and binary_function, as appropriate.[13]

[13] The function objects in the standard C++ library are required to be derived from one of these two templates. However, the call wrappers defined in the standard C++ library don't rely on this inheritance; rather, they rely on the presence of the member type names that these bases provide. If you write your own function objects, you don't have to use unary_function or binary_function, but you do have to provide the required type names.

These nested types are used by the standard C++ library call wrapper types to determine their own argument types and return types. For example, std::binder1st has a constructor that takes a function object and a value, as well as a function call operator that takes another value and returns the result of calling the function object with the two values. For example:

#include <functional>
void test()

{ // simple example of std::binder1st
typedef std::minus<int> int_minus;
int_minus sub;
std::binder1st<int_minus, int> two_minus(sub, 2);
two_minus(1);   // returns sub(2,1)
}

The implementation code for std::binder1st uses the nested typedefs in std::minus to determine the argument type and the return type for its function call operator. Here's a simplified version of its declaration:[14]

[14] In particular, I've used explicit typedefs for argument_type and result_type to make it clearer where they come from. The library code uses the template std::unary_function to define these names.

template <class Op>
struct binder1st
     {   // interface to std::binder1st
     typedef typename
       Op::second_argument_type argument_type;
     typedef typename Op::result_type result_type;
     binder1st(const Op&,
                 const typename Op::first_argument_type&);
     result_type operator()(const argument_type&) const;
     };

Since the function call operator defined by binder1st takes one argument, the template defines the nested type argument_type. The value passed to the function call operator is, in turn, passed as the second argument in the call to the function call operator defined by Op, so binder1st defines argument_type as a synonym for Op::second_argument_type.

The TR1 library function object templates use a different scheme to determine their return type and argument types. As mentioned earlier, the return type and argument types for function are all included in the template argument. The rest of the templates define their function call operator as a template member function, so it gets its argument types from the arguments you pass when you call it. This means that, in general, it's not possible to define nested type names for the argument types, because they aren't known when the function object template is instantiated; it's only at the point of the call that the argument types are known. Therefore, some of the usage patterns that work with function objects from the standard C++ library won't work with function objects from the TR1 library.

Example 6.3. Incompatible (funobjover/fails.cpp)

#include <functional>
using std::not1; using std::bind1st;
using std::tr1::bind;
using namespace std::tr1::placeholders;
using std::binary_function;

struct do_something :
  binary_function<double, double, double>
  { // useless example of callable type with binary function call operator
  double operator()(double, double) const;
  };

void okay()
  { // C++03 call wrapper provides nested types
  not1(bind1st(do_something(), 1.0));
  }

void fails()
  { // TR1 call wrapper does not provide nested types
  not1(bind(do_something(), 1.0, _1));
  }

If you compile this code, the function okay will compile without problems. The function fails, as its name suggests, won't compile. The function call bind(do_something(), 1.0, _1) is the TR1 equivalent of the bind1st call in the function okay. The second function fails because the type returned by the call to bind does not define the nested member argument_type, and the function not1 tries to use that nested name.

TR1 has a partial solution to making code that uses the TR1 library work with the existing standard C++ library function objects. The details depend on which of the TR1 function objects is being used. Generally speaking, when the target object takes one or two arguments and its type clearly defines the types of its arguments, the call wrapper defines the appropriate typedefs for its argument types. Often, the call wrapper can be called with more than one type related to its argument type, [15] but it can provide only one typedef for each of its argument types, so any additional types are simply not available to function objects from the standard C++ library. This is discussed in more detail for each of the TR1 library function objects.

[15] For example, the object returned by mem_fn (Chapter 7) can be called with an object or a pointer, but there's no way to say that in a single typedef, so TR1 chooses Ty* as its argument_type or first_argument_type.


Exercises

Exercise 1

For each of the following errors, write a simple test case containing the error, and try to compile it. In the error messages, look for the key words that relate to the error in the code.

  1. Specializing result_of with a type argument having a different number of types in its argument list than the callable type actually takes.

  2. Specializing result_of with a type argument whose callable type is a class having neither a nested type named result_type nor a nested template named result and that names at least one type in its argument list.

Exercise 2

For each of these uses of INVOKE, write the equivalent code, give its return type, and state whether the code is valid. Use the following declarations and definitions:

void func(int,double,double);
int func(int,double);

struct S
  {
  void mem_fun0(int) const;
  double mem_fun1(long,int) const;
  int mem_data;
  const int cmem_data;
  };
S s0;
const S s1;
const S *ptr = new S;
shared_ptr<S> sp(ptr);

struct oper
  {
  bool operator()() const;
  int operator()(int,double) const;
  };
oper op;

  1. INVOKE(func, 1, 2, 3)

  2. INVOKE(func, 1, 2)

  3. INVOKE(func, 1, 2.0, double)

  4. INVOKE(&S::mem_fun0, s0, 1)

  5. INVOKE(&S::mem_fun0, s1, 1L, 2)

  6. INVOKE(&S::mem_fun1, s1, 1L, 2)

  7. INVOKE(&S::mem_fun1, ptr, 1L, 2)

  8. INVOKE(&S::mem_fun0, sp, 1)

  9. INVOKE(&S::mem_data, s0)

  10. INVOKE(&S::cmem_data, s0)

  11. INVOKE(&S::mem_data, s1)

  12. INVOKE(&S::cmem_data, s1)

  13. INVOKE(op)

  14. INVOKE(op, 1, 1.0)

Exercise 3

Q1:

Each part of this exercise has a type definition, an object of that type, and an expression that calls that object. For each of these expressions, what is the type of the result of that expression, what should result_of::type be for the types used in that expression under the compiler compromise rules, and what is the type of result_of::type using your implementation of the TR1 library? For example:

Type: | typedef float(*t)(float);
Object: | t obj = cosf;
Expression: | obj(1.0)

The return type of obj(1.0) is float, the type of result_of::type is supposed to be float, and with the Dinkumware implementation of the TR1 library, the type of result_of::type is float. (Some of the exercises are a little more difficult than this.)

The exercises use the following definitions:

// types
struct S
{
void f();
int m;
double d;
};
struct S1
{
bool operator()() const;
};

struct S2
{
bool operator()() const;
typedef bool result_type;
};

struct S3
{
bool operator()() const;
int operator()(int) const;
};

struct S4
{
bool operator()() const;
int operator()(int) const;
typedef bool result_type;
};

// objects
S s;
const S cs;
S1 s1;
S2 s2;
S3 s3;
S4 s4;

1. | Type: | typedef void(S::*t0)();
 | Object: | t0 obj0 = &S::f;
 | Expression: | (s.*obj0)()
2. | Type: | typedef int S::*t1;
 | Object: | t1 obj1 = &S::m;
 | Expression: | s.*obj1
3. | Type: | typedef double S::*t2;
 | Object: | t2 obj2 = &S::d;
 | Expression: | cs.*obj2
4. | Type: | S1
 | Object: | S1 obj3;
 | Expression: | obj3()
5. | Type: | S2
 | Object: | S2 obj4;
 | Expression: | obj4()
6. | Type: | S3
 | Object: | S3 obj5;
 | Expression: | obj5(1)
7. | Type: | S4
 | Object: | S4 obj6;
 | Expression: | obj6(1)


Chapter 7. The mem_fn Function Template

The conditionings associated with a particular class ...produce habitus, structured structures predisposed to function as structuring structures ....

The Logic of Practice
PIERRE BOURDIEU, TRANSLATED BY RICHARD NICE

template <class Ret,class Ty>
  unspecified mem_fn(Ret Ty::*pm);

The function template returns a simple call wrapper cw, with a weak result type (see Section 6.2), such that the expression cw(a1, a2, ..., aN) is equivalent to INVOKE (pm, a1, a2, ..., aN) (see Section 6.2).

The returned call wrapper is derived from std::unary_function<cv Ty*, Ret>hence defining the nested type result_type as a synonym for Ret and the nested type argument_type as a synonym for cv Ty* only if the type Ty is a pointer to member function with cv-qualifier cv that takes no arguments.

The returned call wrapper is derived from std::binary_function<cv Ty*, T2, Ret>hence defining the nested type result_type as a synonym for Ret, the nested type first argument_type as a synonym for cv Ty*, and the nested type second argument_type as a synonym for T2only if the type Ty is a pointer to member function with cv-qualifier cv that takes one argument, of type T2.

This means that you can call the function template mem_fn with a pointer to a class member and get back an object that acts like an ordinary function but uses its first argument to identify the object that the member pointer should be applied to.

Example 7.1. Binding to Object (funobjmem/bindobj.cpp)

#include <functional>
#include <memory>
#include <iostream>
using std::tr1::mem_fn; using std::tr1::shared_ptr;
using std::cout;

class C
  { // simple class with member function
public:
  C(int i0 = 0) : i(i0) {}
  void show() const
    { // show contents
    cout << i << '\n';
    }
private:
  int i;
  };

template <class Fty,class Ty>
void apply(Fty fn,Ty obj)
  { // call a function object with one argument
  fn(obj);
  }

int main()
  { // demonstrate simple use of mem_fn
  C c0(0);
  C *cp = new C(1);
  shared_ptr<C> sp(new C(2));
  void (C::*mptr)() const = &C::show;

  apply(mem_fn(mptr),c0); // equivalent to (c0.*mptr)()
  apply(mem_fn(mptr),cp); // equivalent to (cp->*mptr)()
  apply(mem_fn(mptr),sp); // equivalent to ((*sp).*mptr)()

  delete cp;
  return 0;
  }

As you can see, the object that this code creates with mem_fn(mptr) can be called with an object, a pointer, or a shared_ptr as its argument; the compilerwith a little help from some metaprogramming in the <functional> headerfigures out how to call the object. This is a big improvement over the standard C++ library's std::mem_fun and std::mem_fun_ref, which require you to decide at the point where you create the call wrapper whether you are going to call it with a pointer or an object.

Of course, you can also call member functions that take their own set of arguments. You simply pass those arguments at the point where you call the call wrapper, after the argument that gives the object.

Example 7.2. Additional Arguments (funobjmem/additional.cpp)

#include <functional>
#include <iostream>
using std::tr1::mem_fn;
using std::cout;

class C
  { // simple class with member functions
public:
  C(int i0 = 0) : i(i0) {}
  void show() const
    { // show contents
    cout << "in show: " << i << '\n';
    }
  void one_arg(int j) const
    { // member function taking one argument
    cout << "in one_arg: " << i
         << "," << j << '\n';
    }
  void two_args(int j,int k) const
    { // member function taking two arguments
    cout << "in two_args: " << i
         << "," << j << "," << k << '\n';
    }
private:
  int i;
  };

int main()
  {
  C c(1);
  int two = 2;
  int three = 3;
  mem_fn(&C::show)(c);               // c.show();
  mem_fn(&C::one_arg)(c,two );       // c.one_arg(two);
  mem_fn(&C::two_args)(c,two,three); // c.two_args(two,three);
  return 0;
  }

For backward compatibility (see Section 6.5), the object returned by a call to mem_fn is derived from std::unary_function or std::binary_function when appropriate. This defines the nested types that are used by callable objects from the standard C++ library. When the argument to mem_fn is a pointer to a member function of a class Ty and the function takes no arguments, the type of the returned object is derived from unary_function, instantiated with one argument that names the type Ty*[1] and one argument that names the result type. When the argument to mem_fn is a pointer to a member function of a class Ty and the function takes one argument, the type of the returned object is derived from binary_function, instantiated with one argument that names the type Ty*, one argument to pass to the member function, and one argument that names the result type.

[1] That is, it asserts that a mem_fn object that holds a pointer to a member of class Ty can be called with an argument of type Ty* but does not assert that it can be called with an argument of type Ty.

Example 7.3. Nested Types (funobjmem/nested.cpp)

#include <functional>
#include <iostream>
#include <typeinfo>
#include <utility>
using std::tr1::mem_fn;
using std::unary_function; using std::binary_function;
using std::cout;

void show_types(...)
  { // general function
  cout << "not unary_function or binary_function\n";
  }

template <class Ty,class Ret>
void show_types(
  const unary_function<Ty,Ret>& obj)
  { // overload for types derived from unary_function
  typedef unary_function<Ty,Ret> base;
  cout << "unary_function:"
       << typeid(base::result_type).name() << '('
       << typeid(base::argument_type).name() << ")\n";
  }

template <class Ty1,class Ty2,class Ret>
void show_types(
  const binary_function<Ty1,Ty2,Ret>& obj)
  { // overload for types derived from binary_function
  typedef binary_function<Ty1,Ty2,Ret> base;
  cout << "binary_function:"
       << typeid(base::result_type).name() << '('
       << typeid(base::first_argument_type).name()
       << ","
       << typeid(base::second_argument_type).name()
       << ")\n";
  }

class C
  { // simple class with member functions
public:
  C(int i0 = 0) : i(i0) {}
  void show() const
    { // show contents
    cout << i << '\n';
    }
  void set(int i0)
    { // replace contents
    i = i0;
    }
private:
  int i;
  };

int main()
  { // show nested types
  show_types(mem_fn(&C::show));
  show_types(mem_fn(&C::set));
  return 0;
  }

For member functions that take more than one argument, the type returned by mem_fn has a nested type named result_type that is a synonym for the return type of the member function.

Example 7.4. Nested Type result_type (funobjmem/resulttype.cpp)

#include <functional>
#include <iostream>
using std::tr1::mem_fn;
using std::cout;

template <class Ty>
void show_result_type(Ty)
  { // show nested type named result_type
  cout << typeid(Ty::result_type).name() << '\n';
  }

struct S
  { // struct with member functions
  int f0() { return 0; }
  long f1(int) { return 1; }
  void f2(int,int) {}
  double f3(int,int,int) { return 2.0; }
  };

int main()
  { // show nested result  type
  show_result_type(mem_fn(&S::f0)); // S::f0 returns int
  show_result_type(mem_fn(&S::f1)); // S::f1 returns long
  show_result_type(mem_fn(&S::f2)); // S::f2 returns void
  show_result_type(mem_fn(&S::f3)); // S::f3 returns double
  return 0;
  }

We've been looking at member functions; you can also call mem_fn with a pointer to member data. The resulting object can be used in the same way as an object that holds a pointer to member function that takes no arguments.

Example 7.5. Pointer to Member Data (funobjmem/memdata.cpp)

#include <functional>
#include <iostream>
#include <typeinfo>
using std::tr1::mem_fn;
using std::cout;

template <class Ty>
void show_type(Ty)
  { // show the name of a type
  cout << typeid(Ty ).name() << '\n';
  }

struct S
  {
  S() : i(0), j(1) {}
  int i;
  const int j;
  };

int main()
  {
  S s;
  const S cs;
  show_type(mem_fn(&S::i)(s));  // type of s.i
  show_type(mem_fn(&S::i)(cs)); // type of cs.i
  show_type(mem_fn(&S::j)(s));  // type of s.j
  show_type(mem_fn(&S::j)(cs)); // type of cs.j
  }


Exercises

Exercise 1

For each of the following errors, write a simple test case containing the error, and try to compile it. In the error messages, look for the key words that relate to the error in the code.

  1. Attempting to call mem_fn with an argument that isn't a pointer to member

  2. Attempting to call the returned object with a pointer to a type that isn't the class that the member belongs to or a class derived from that class

  3. Attempting to call the returned object with too few arguments

  4. Attempting to call the returned object with too many arguments

Exercise 2

Write a class that holds a private data member of type int and has a member function named show that shows the value of that data member. Write a program that creates an object, using std::vector, that can hold objects of this type and populates it with a dozen or so objects with distinct values in their private data member.

  1. Use the algorithm std::for_each and std::mem_fun_ref to show the value stored in each of these data objects.

  2. Use the algorithm std::for_each and std::tr1::mem_fn to show the value stored in each of these data objects.

Exercise 3

Copy the code from the previous exercise. Change the vector to hold pointers to objects instead of objects, and make all the other changes needed to make the program work correctly.

Exercise 4

Copy the code from the previous exercise. Change the vector to hold std::tr1::shared_ptr objects to point to the contained objects, and make all the other changes needed to make the program work correctly. Caution: Part of the previous program can't be made to work correctly after this change.

Exercise 5

Write a class that has a member function that takes one argument with a default value. Write a program that calls mem_fn with a pointer to this member function and calls the returned object.

Exercise 6

Write a class that has two member functions with the same name and return type but take two distinct argument lists. Write a program that makes two calls to mem_fn, with pointers to these two member functions, and calls the returned objects.

Exercise 7

Write a class that has a private data member and two access functions, both named value. One version of value should be callable on a modifiable object and should return a reference to the stored data member; the other should be callable only on a const object and should return a const reference to the stored data member. Write a program that makes two calls to mem_fn, with pointers to these two member functions, and calls the returned objects.


Chapter 8. The reference_wrapper Class Template

These are only aliases. Their real names are Stuhldreher, Miller, Crowley, and Layden.

Story on Notre Dame football victory over Army
GRANTLAND RICE

The class template reference_wrapper creates objects that act like references but can be copied. Ordinary references can't be copied.

Example 8.1. Copying References (funobjref/refcopy.cpp)

#include <functional>
using std::tr1::reference_wrapper;

class ref
  { // simple class containing reference
public :
  ref(int& i) : member(i) {}
private :
  int& member;
  };

class refwrap
  { // simple class containing reference_wrapper
public :
  refwrap(int& i) : member(i) {}
private :
  reference_wrapper<int> member;
  };

void f()
  { // demonstrate copying
  int i, j;
  ref r0(i);
  ref r1(j);
  r1 = r0 ;        // error: ref can't be copied

  refwrap rw0(i);
  refwrap rw1(j);
  rw1 = rw0 ;     // okay: refwrap can be copied
  }

An object of type reference_wrapper<Ty> can be implicitly converted to a reference to Ty and has a member function, named get, that returns a reference to Ty. Finally, if the type Ty is a callable type, you can use the object's function call operator to call the object it refers to.

template<class Ty>
   class reference_wrapper
    : public unary_function<T1, Ret>         // see Section 8.2
    : public binary_function<T1, T2, Ret>    // see Section 8.2
  {
public :
  typedef Ty type;
  typedef T0 result_type;                     // see Section 8.2
  explicit reference_wrapper(Ty&);
  Ty& get() const;
  operator Ty&() const;
  template <class T1, class T2,..., class TN>
  typename result_of<T(T1, T2,..., TN)>::type
  operator() (T1&, T2&, ..., TN&) const ;     // see Section 8.3
  };


Section 8.1. Creation

8.1. Creation

You can create a reference_wrapper object directly with the template's constructor, and you can create a reference_wrapper object indirectly by calling the functions ref and cref.

explicit reference_wrapper::reference_wrapper(Ty& obj);

The constructor constructs an object that refers to obj.

Example 8.2. Construction (funobjref/construct.cpp)

#include <functional>
#include <iostream>
using std::tr1::reference_wrapper;
using std::cout;

int main()
  { // demonstrate basic use of reference_wrapper
  int Stuhldreher = 3;
  reference_wrapper<int> rw(Stuhldreher);
  cout << rw << '\n';           // displays value of Stuhldreher
  Stuhldreher = 4;
  cout << rw << '\n';           // displays new value of Stuhldreher
  rw.get() = 5;                 // changes value of Stuhldreher
  cout << Stuhldreher << '\n';  // displays new value
  return 0;
  }

template <class Ty>
  reference_wrapper<const Ty> cref(
    const Ty& obj);
template <class Ty>
  reference_wrapper <const Ty> cref(
    reference_wrapper <Ty> rw);
template <class Ty>
  reference_wrapper <Ty> ref(
    Ty& obj);
template <class Ty>
  reference_wrapper <Ty> ref(
    reference_wrapper <Ty> rw);

The first function template returns an object of type reference_wrap-per<const Ty> that refers to obj. The second function template returns an object of type reference_wrapper<const Ty> that refers to rw.get(). The third function template returns an object of type reference_wrap-per<Ty> that refers to obj. The fourth function template returns an object of type reference_wrapper<Ty> that refers to rw.get().

Example 8.3. Function Templates ref and cref (funobjref/refcref.cpp)

#include <functional>
#include <iostream>
using std::tr1::reference_wrapper;
using std::tr1::ref; using std::tr1::cref;
using std::cout;
void show(int& i)
  { // show value referred to by reference to int
  cout << "int &:" << i << '\n';
  }

void show(const int& i)
  { // show value referred to by reference to const int
  cout << "const int&:" << i << '\n';
  }

int main()
  { // demonstrate use of ref and cref
  int Miller = 3;
  show(ref(Miller));    // calls show(int&);
  reference_wrapper<int> rw0(Miller);
  show(ref(rw0));       // calls show(int&);
  show(cref(Miller));   // calls show(const int&);
  reference_wrapper <const int> rw1(Miller);
  show(cref(rw1));      // calls show(const int&);
  return 0;
  }

One important difference between using the constructor for reference_wrapper directly and using either of the functions ref and cref is that these functions return a reference_wrapper<Ty> object, where Ty is the type of their argument. The constructor, on the other hand, can be passed an object of a type that is convertible to the type Ty that the reference_wrapper object holds. Thus, although reference_wrapper itself directly supports polymorphic types, the functions ref and cref do not; it takes a bit of trickery to get these functions to return a reference_wrapper that refers to a base of the type of their argument. We'll look at how to do that in the exercises.

Example 8.4. Polymorphic Types (funobjref/polymorph.cpp)

#include <functional>
#include <iostream>
using std::tr1::reference_wrapper;
using std::cout;

struct base
  {  // base class
  virtual void show() const

    {  // show name of base class
    cout << "base\n";
    }
  };

struct derived0 : base
  { // one derived class
  void show() const
    { // show name of derived class
    cout << "derived0\n";
    }
  };

struct derived1 : base
  { // another derived class
  void show() const
    { // show name of derived class
    cout << "derived1\n";
    }
  };

int main()
  { // demonstrate reference_wrapper's support for polymorphism
  derived0 Crowley ;
  derived1 Layden ;
  reference_wrapper<base> rw0(Crowley);
  rw0.get().show();         // calls derived0::show
  reference_wrapper<base> rw1 (Layden);
  rw1.get().show();         // calls derived1::show
  return 0;
  }


Section 8.2. Nested Types

8.2. Nested Types

typedef Ty reference_wrapper::type ;

The nested type reference_wrapper<Ty>::type is a synonym for the template argument Ty.

typedef T0 reference_wrapper::result_type;

The template specialization reference_wrapper<Ty> is derived from std::unary_function<T1, Ret>hence defining the nested type result_type as a synonym for Ret and the nested type argument_type as a synonym for T1only if the type Ty is one of the following:

  • A function type or pointer to function type taking one argument of type T1 and returning Ret

  • A pointer to member function type with cv-qualifier cv that takes no arguments; the type T1 is cv Ty*, and Ret is the return type of the pointer to member function

  • A type that is derived from std::unary_function<T1, Ret>

The template specialization reference_wrapper<Ty> is derived from std::binary_function<T1, T2, Ret>hence defining the nested type result_type as a synonym for Ret, the nested type first_argument_type as a synonym for T1, and the nested type second_argument_type as a synonym for T2only if the type Ty is one of the following:

  • A function type or pointer to function type taking two arguments of types T1 and T2 and returning Ret

  • A pointer to member function type with cv-qualifier cv that takes one argument of type T2; the type T1 is cv Ty*, and Ret is the return type of the pointer to member function

  • A type that is derived from std::binary_function<T1, T2, Ret>

If it is not derived from unary_function or binary_function, the template specialization defines the nested type result_type according to the rules for a weak result type (see Section 6.2).


Section 8.3. Invocation

8.3. Invocation

typename result_of <Ty(T1, T2, ..., TN)>::type
  operator()(T1&, T2&, ...,TN&) const;

If the template argument Ty is not a callable type, this operator is not present. For a callable type (see Section 6.1)Ty and an object rw of type reference_wrapper<Ty>, the expression rw(a1, a2, ..., aN) is equivalent to INVOKE(rw.get(), a1, a2, ..., aN) (see Section 6.2).

When a reference_wrapper object holds a callable object, you can call the reference_wrapper object, which will, in turn, call its target object.

Example 8.5. Invoking (funobjref/invoke.cpp)

#include <functional>
#include <iostream>
using std::tr1::reference_wrapper; using std::tr1::cref;
using std::cout;

void hello()
  {   // simple function
  cout << "Hello, world\n";
  }

void goodbye()
  {   // another simple function
  cout << "Goodbye, cruel world\n";
  }

int main()
  {   // demonstrate invocation of reference  wrapper object
  typedef void (*const fun)();
  reference_wrapper<fun> rw(&hello);
  rw();           // calls hello
  rw = cref(&goodbye);
  rw();           // calls goodbye
  return 0;
  }

If you look at the declaration of reference_wrapper's function call operator, you'll see that all the arguments are passed by reference. This lets you pass modifiable objects to the target object.

Example 8.6. Modifiable Arguments (funobjref/modifiable.cpp)

#include <functional>
#include <iostream>
using std::tr1::reference_wrapper;
using std::cout;

struct S
  {
  void operator()(int& i)
    {   // modify argument
    ++i;
    }
  typedef void result_type;
  };

int main()
  {
  int i = 0;
  S s;
  reference_wrapper<S> rw(s);
  cout << "Before call :" << i << '\n';
  rw(i);
  cout << "After call: "<< i << '\n';
  return 0;
  }


Exercises

Exercise 1

For each of the following errors, write a simple test case containing the error, and try to compile it. In the error messages, look for the key words that relate to the error in the code.

  1. Attempting to construct a reference_wrapper<int> object from an object of type const int

  2. Attempting to modify an object of type int through an object of type reference_wrapper<const int>

  3. Attempting to assign an object of type reference_wrapper<T1> to an object of type reference_wrapper<T2>, where T1 and T2 are unrelated types

  4. Attempting to assign an object of type reference_wrapper<T1> to an object of type reference_wrapper<T2>, where T1 is publicly derived from T2

  5. Attempting to use a reference_wrapper object to call an object that isn't callable

  6. Attempting to call a target object with the wrong number of arguments

Exercise 2

Write a program that does the following:

  1. Creates an object of type int and initializes it to 1

  2. Creates an object of type int& and an object of type const int&, both referring to the object of type int

  3. Constructs a reference_wrapper object that refers to the int object and a reference_wrapper that refers to the int object but doesn't allow modification of that object

Exercise 3

Write a program that does the following:

  1. Defines a base type and a type derived from the base type

  2. Creates an object of the derived type

  3. Creates a reference to the base type that refers to the derived object

  4. Creates a const reference to the base type that refers to the derived object

  5. Constructs a reference_wrapper<base> object that refers to the derived object

  6. Constructs a reference_wrapper<const base> object that refers to the derived object

  7. Creates a second object of the derived type

  8. Uses ref to reassign the first reference_wrapper object to refer to the new object

  9. Uses cref to reassign the second reference_wrapper object to refer to the new object

Exercise 4

Write a program that creates a reference_wrapper object that holds a pointer to the function std::cosf. Call the function several times, with different argument values, directly and through the reference_wrapper object, and verify that the results are the same.

Exercise 5

Write a program that defines a class with a member function that takes at least one argument, then creates a reference_wrapper object that holds a pointer to that member function. Create several objects of that class type, and call the member function several times, with different argument values, directly and through the reference_wrapper object, and verify that the results are the same.

Exercise 6

Write a program that defines a class with a member function call operator that takes at least one argument, then creates a reference_wrapper object that holds an object of that type. Call the operator several times, with different argument values, directly and through the reference_wrapper object, and verify that the results are the same.


Chapter 9. The function Class Template

Form ever follows function.

"The Tall Office Building Artistically Considered," from Lippincott's Magazine
LOUIS HENRI SULLIVAN

One of the drawbacks of template programming is the proliferation of template instantiations. If you write a function template that takes a callable type as one of its type arguments and makes a function call through an object of that type, the code that is generated for an instantiation with a pointer to function is distinct from the code that is generated for an instantiation with a class type T1 that has a function call operator, and that code is distinct from the code that is generated for an instantiation with a different class type T2 that also has a function call operator. Further, additional template code that uses this template will also splinter into multiple instantiations, as will template code that uses this additional template code, and so on.[1]

[1] Of course, template programming zealots declare that this is primarily a compiler problem and that someday wonderful compilers will eliminate template code bloat. Today, however, the problem is real and has to be considered in any library design.

Old-fashioned C++ designers recognize this as the classic case for the use of polymorphism.[2] By factoring the code into a common part and several specialized parts, one for each distinct callable type, and defining a uniform interface to these specialized parts, supported by an abstract class, we can give up a bit of speed in exchange for reduced code size.[3] All these details can be hidden by wrapping them in a template whose type argument provides the argument types and return type for the resulting template instance's function call operator. Once this is done, a template function that calls through that specialization needs to be instantiated only once, regardless of how many callable types that wrapper is used with, because there is only one template specialization for the wrapper.

[2] In the old-fashioned sense, now sometimes referred to as "runtime polymorphism."

[3] Unlike direct calls from template code, the virtual function calls from the common code to the specialized types typically won't be inlined.

The argument types and return type are described by a function type, which is a return type followed by a left parenthesis followed by an argument list, which can be empty, followed by a right parenthesis. For example, the function type of the standard function float cosf(float) is float(float); the function type of the standard function int rand() is int().

The class template function creates polymorphic function objects. The argument to the template must be a function type that describes the argument types and return type of objects of the template type. These objects can hold any target object that can be called with those argument types and returns a type that can be converted to the object's return type. For example, the type function<float(float)> can hold the function pointer cosf as its target object. The target object can be reassigned at runtime.

template <class Fty> // Fty of type Ret(T1, T2, ..., TN)
class function {
  : public unary_function<T1, Ret>      // see Section 9.5
  : public binary_function<T1, T2, Ret> // see Section 9.5
public :
  typedef Ret result_type;
  function();
  function(null_ptr_type npc);
  function(const function & right);
  template<class Fty2>
    function(Fty2 right);
  template<class Fty2>
    function(reference_wrapper<Fty2> fnref);

  function& operator=(const function& right);
  function& operator=(null_ptr_type npc);
  template<class Fty2>
    function& operator=(Fty2 right);
  template<class Fty2>
    function& operator=(reference_wrapper<Fty2> fnref);
  void swap(function& right);

  operator boolean-type()  const;

  result_type operator()(T1, T2, ..., TN) const;
  const type_info & target_type() const;
  template<class Fty2> Fty2 *target();
  template<class Fty2> const Fty2 *target() const;

private :
  template<class Fty2>
    bool operator==(const Fty2&) const;
  template<class   Fty2>
    bool operator!=(const Fty2&) const;
  };

class bad_function_call  :  public std::exception {
};

An empty function object does not hold a callable object or a reference to a callable object. The class bad_function_call describes an exception thrown to indicate that a call to operator() on a function object failed because the object was empty.

Some member functions take an operand that names a callable object. You can specify such an operand in several ways:

  • fn: A callable object. After the call, the function object holds a copy of fn.

  • fnref: A reference_wrapper object holding a reference to a callable object. After the call, the function object holds a reference to fnref.get().

  • right: Another function object. After the call, the function object holds the same callable object as right.

  • npc: A null pointer constant. After the call, the function object is empty. The member function takes an implementation-specific argument type that ensures that it cannot be called with a pointer that is not null or with an integral constant.

The member operators operator== and operator!= are private and not defined, so they cannot be called. But see Section 9.4 for comparisons with null pointers.


Section 9.1. Constructing a function Object

9.1. Constructing a function Object

function::function();
function::function(null_ptr_type  npc);
function::function(const function& right);
template <class Fty2>
  function::function(Fty2 fn);
template <class Fty2>
  function::function(reference_wrapper <Fty2> fnref);

The first two constructors construct an empty function object. The other constructors construct a function object that holds the callable object passed as the operand.

Example 9.1. Constructing function Objects (funobjfun/construct.cpp)

#include <functional>
#include <iostream>
using std::tr1::function;
using std::cout;

int func()
  { // simple function
  return   0;
  }

struct S
  { // simple function object
  int operator()() const
    {
    return 1;
    }
  typedef int result_type;
  } obj;

void report (const char *title, bool val)
  { // report state of function object
  cout << title << ": object is";
  if (val)
    cout << "not";
  cout << "empty\n";
  }

int main()
  { // demonstrate construction of function<> types
  function <int()> f0;
  report("after default construction", f0);
  function <int()> f1(0);
  report("after construction from 0", f1);
  function <int()> f2(f1);
  report("after construction from f1", f2);
  function <int()> f3(func);
  report("after construction from func", f3);
  function <int()> f4(obj);
  report("after construction from obj", f4);
  return 0;
  }


Section 9.2. Access

9.2. Access

function::operator boolean-type() const;

The member operator returns an object of an unspecified type that is convertible to bool; the converted value is false only if *this is empty.

Example 9.2. Member operator boolean-type (funobjfun/boolean.cpp)

#include <functional>
#include <iostream>
#include <math.h>
using std::tr1::function;
using std::cout;

void report (const char *title, bool val)
  { // report state of function object
  cout << title << ": object is ";
  if (val)
    cout << "not ";
  cout << "empty\n";
  }

int main ()
  { // demonstrate conversion to boolean type
  function <float(float)> fn;           // construct empty object
  report("after construction", fn);
  fn = cosf;                            // assign target object
  report("after assigning target object", fn);
  fn = 0;                               // assign null pointer
  report("after assigning null pointer", fn);
  return 0;
  }


Section 9.3. Modification

9.3. Modification

function& function::operator=(const function& right);
function& function::operator=(null_ptr_type   npc);
template<class Fty2>
  function& function::operator=(Fty2 right);
template<class Fty2>
  function& function::operator=(
    reference_wrapper <Fty2> fnref);

The operators each replace the callable object, if any, held by *this with the callable object passed as the operand.

Example 9.3. Assigning to function Objects (funobjfun/assign.cpp)

#include <functional>
#include <iostream>
using std::tr1::function;
using std::cout;

int func()
  { // simple function
  return 0;
  }

struct S
  { // simple function object
  int operator()() const
    {
    return 1;
    }
  typedef int result_type;
  } obj;

void report(const char *title, bool val)
  { // report state of function object
  cout << title << ": object is ";
  if (val)
    cout << "not ";
  cout << "empty \n";
  }

int main()
  { // demonstrate assignment of function<> types
  function<int()> f0(func), f1;
  report("constructed from func", f0);
  f0 = f1;
  report("assigned empty function object", f0);
  f0 = func;
  report("assigned func", f0);
  f0 = 0;
  report("assigned 0", f0);
  f0 = obj;
  report("assigned obj", f0);
  return 0;
  }

void function::swap(function& right);

The member function swaps, in constant time, the callable objects between *this and right and throws no exceptions.

Example 9.4. function::swap (funobjfun/swap.cpp)

#include <functional>
#include <iostream>
using std::tr1::function;
using std::cout;

int func()
  { // simple function
  return 0;
  }

void report(const char *title, bool val)
  { // report state of function object
  cout << title << ": object is ";
  if (val)
    cout << "not ";
  cout << "empty\n";
  }

int main()
  { // demonstrate swapping of function<> types
  function<int()> f0;
  function<int()> f1(func);
  report("f0 before swap", f0);
  report("f1 before swap", f1);
  f0.swap(f1);
  report("f0 after swap", f0);
  report("f1 after swap", f1);
  return 0;
  }


Section 9.4. Comparisons

9.4. Comparisons

template<class Fty>
  bool operator==(const function<Fty>& func,
    null_ptr_type   npc);
template<class Fty>
  bool operator==(null_ptr_type   npc,
    const function<Fty>& func);

The functions return true only if the argument func is empty. The argument npc must be a null pointer constant.

Example 9.5. Null Pointer Constant (funobjfun/opequal.cpp)

#include <functional>
#include <iostream>
#include <math.h>
using std::tr1::function;
using std::cout;

void report(const char *title, bool val)
  { // report state of function object
  cout << title << ": object is ";
  if (!val)
    cout << "not ";
  cout << "empty\n";
  }

int main()
  { // demonstrate comparison to null pointer constant
  function<float(float)> fn;         // construct empty object
  report("after construction", fn == 0);
  fn = cosf;                        // assign target object
  report("after assigning target object", 0 == fn);
  fn = 0;                           // assign null pointer
  report("after assigning null pointer", fn == 0);
  return 0;
  }

template<class Fty>
  bool operator!=(const function<Fty>&,
    null_ptr_type   npc);
template<class Fty>
  bool operator!=(null_ptr_type   npc,
    const function<Fty>&);

The functions return true only if the argument func is not empty. The argument npc must be a null pointer constant.


Section 9.5. Nested Types

9.5. Nested Types

typedef Ret function::result_type;

The typedef is a synonym for the Ret type in the template's function type argument.

The template specialization function<Fn> is derived from std::unary_-function<T1, Ret>hence defining the nested type result_type as a synonym for Ret and the nested type argument_type as a synonym for T1only if Fn is a function type that takes one argument.

The template specialization function<Fn> is derived from std::binary_-function<T1, T2, Ret>hence defining the nested type result_type as a synonym for Ret, the nested type first_argument_type as a synonym for T1, and the nested type second_argument_type as a synonym for T2only if Fn is a function type that takes two arguments.


Section 9.6. Invocation

9.6. Invocation

result_type function::operator()(
  T1 t1, T2 t2, ..., TN tN) const;

The member function throws an exception object of type bad_function_-call if *this is empty; otherwise, it returns INVOKE_R (fn, t1, t2, ..., tN, Ret), where fn is the callable object held by *this.

Example 9.6. Invocation (funobjfun/invoke.cpp)

#include <functional>
#include <iostream>
using std::tr1::function;
using std::cout;

int func()
  { // simple function
  cout << "called func\n";
  return 0;
  }

struct S
  { // simple function object
  int operator()() const
    {
    cout << "called S::operator()\n";
    return 1;
    }
  typedef int result_type;
  } obj;

int main()
  { // demonstrate construction of function<> types
  function<int ()> f0(func);
  f0();
  f0 = obj;
  f0();
  return 0;
  }


Section 9.7. The Target Object

9.7. The Target Object

const type_info& function::target_type()  const;

The member function returns a reference to an object of type type_info that describes the type of the current target object.

Example 9.7. function::target_type (funobjfun/targettype.cpp)

#include <functional>
#include <iostream>
#include <typeinfo>
#include <math.h>
using std::tr1::function;
using std::cout; using std::type_info;

struct S
  { // simple callable type
  float operator()(float) { return 1.0f; }
  typedef float result_type;
  };

void show_type(const char *title, const type_info& info)
  { // show name of target type
  cout << title << ": " << info.name() << '\n';
  }

int main()
  { // demonstrate function::target_type
  function<float(float)> fn;
  show_type("empty", fn.target_type());
  fn = cosf;
  show_type("cosf", fn.target_type());
  fn = S();
  show_type("S", fn.target_type());
  return 0;
  }

template <class Fty2> Fty2 *function::target();
template <class Fty2> const Fty2 *function::target() const;

The member functions return a pointer to the target object if the target object is of type Fty2; otherwise, they return a null pointer.

Each of these member functions is a function template. Since they do not take any arguments, the compiler can't deduce the template argument types, so you must give the argument type explicitly when you call these functions.

Example 9.8. function::target (funobjfun/target.cpp)

#include <functional>
#include <iostream>
#include <typeinfo>
#include <math.h>
using std::tr1::function;
using std::cout; using std::type_info;

typedef function<float(float)> Fty;
typedef float(*fptr)(float);

struct S
  { // simple callable type
  float operator()(float) { return 1.0f; }
  typedef float result_type;
  };

void show_pointer(const char *title, Fty& fty)
  { // check pointer type and value
  cout << title << ": ";
  if (fty.target<fptr>())
    cout << " target has type pointer to function\n";
  else if (fty.target<S>())
    cout << " target has type S\n";
  else
    cout << " target is empty or has unknown type\n";
  }

int main()
  { // demonstrate function::target_type
  function<float(float)> fn;
  show_pointer("empty", fn);
  fn = cosf;
  show_pointer("cosf", fn);
  fn = S();
  show_pointer("S", fn);
  return 0;
  }


Exercises

Exercise 1

For each of the following errors, write a simple test case containing the error, and try to compile it. In the error messages, look for the key words that relate to the error in the code.

  1. Attempting to construct a function object with a callable type that takes the wrong number of arguments

  2. Attempting to construct a function<float(float)> object with a callable type that takes an argument of type void*

  3. Attempting to compare two function objects for equality

  4. Attempting to compare a function object to a pointer object

Exercise 2

Given an object fn of type function<double(double)>, which of the following objects can be the target object of fn? Write some code to verify your answers.

  1. (double(*)(double))cos,[4] declared in <math.h>

    [4] Unfortunately, the cast is needed to choose among the overloaded versions of cos.

  2. sinf, declared in <math.h>

  3. tanl, declared in <math.h>

  4. ilogbl, declared in <math.h>

  5. srand, declared in <stdlib.h>

  6. Fty f, where Fty is defined as:

struct Fty
  {
  float operator()(double);
  typedef float result_type;
  };

Exercise 3

Write a class named match that stores an integer value that is set to zero by the constructor. Add a member function that changes the stored value to the value of its argument. Add a function call operator that takes an integer argument and returns a Boolean value that is true if the value of the argument is equal to the object's stored value.

Write a program that creates an object of type std::vector<int> and stores several integer values in it.

  1. Use the algorithm std::count_if and a match object to count the number of elements in the vector that are equal to 3.

  2. Use the algorithm std::count_if and a match object to count the number of elements in the vector that are equal to 5.

  3. Create a function object that can hold an object of type match as its target object. Initialize it with the match object from the previous part, and pass the function object to count_if.

  4. Change the stored value of the match object to 7, store the modified match object in the function object, and repeat the search.

  5. Store a reference to the match object in the function object, and repeat the search.

  6. Change the stored value in the match object to 9, and repeat the search.


Chapter 10. The bind Function Template

One Ring to bring them all and in the darkness bind them.

The Fellowship of the Ring
J.R.R. TOLKIEN

Suppose that you have a pair of pointers, first and last, defining a sequence of integer values, and you need to know how many elements in the sequence have a value that is greater than or equal to 10. You can do this with the standard algorithm count_if and a predicate that returns true when called with a value that is greater than or equal to 10. The standard library doesn't have that predicate, but it has less, which takes two arguments and returns true if the first argument is less than the second. If you had a way to tell count_if to always use 10 as the first argument to the less predicate, you'd have the problem solved. That's a simple example of what the TR1 template function bind can do.

Example 10.1. Simple bind Example (funobjbind/simple.cpp)

#include <functional>
#include <iostream>
using std::tr1::bind;
using namespace std::tr1::placeholders;
using std::less; using std::cout;

template <class Pr>
int count_elements(const int *first, const int *last,
  Pr pred)
  { // count elements in the range [first,last) for which pred(elt) is true
  int count = 0;
  while (first != last)
    if (pred(*first++))
      ++count;
  return  count;
  }

int count_ge10(int *first, int *last)
  { // bind 10 as first argument to less<int>
  int val = 10;
  return count_elements(first, last,

    bind(less<int>(), val, _1));
  }

int main()
  { // demonstrate simple uses of bind
  int values[6] = { 1, 3, 19, 12, 6, 11 };
  int count = count_ge10(values, values + 6);
  cout << count
    << "values greater than or equal to 10\n";
  return 0;
  }

The function count_ge10 calls bind with three arguments. The first is the target object. Its type is less<int>, and it has a function call operator that takes two arguments of type int. The second argument is val, with a value of 10. Because it's the first argument after the target object, it tells bind what the first argument to the target object should be. When the object returned by bind is called, the value val will be passed as the first argument to the target object. The third argument is the placeholder _1. Because it's the second argument after the target object, it tells bind what the second argument to the target object should be. The placeholder _1 says that this argument should be the value passed as the first argument when the bind object is called. The resulting bind object is then passed as the predicate to the function template count_elements.[1]

[1] This example also works if you use the standard algorithm count_if, which is remarkably similar to count_elements. The example uses count_elements to show you how the algorithm is implemented.

The function template count_elements steps through the elements of its input range, passing each element in turn to the predicate pred and incrementing count each time the call to pred returns true. In this example, the call to pred(*first++) does the same thing as this code:

less<int> pr;
pr(10, *first++);

That is, the call to bind has bound the value 10 as the first argument to less<int>, producing a predicate that can be called with a single argument of type int that returns true if the value of its argument is greater than or equal to 10.

The function template bind takes a callable object as its first argument and returns a call wrapper whose target object is a copy of the callable object. The function template also takes additional arguments that describe the arguments that will be passed to the target object when it is called. When the additional argument is a value, that value is passed when the target object is called. When the additional argument is a placeholder, the value passed to the bind object's function call operator is passed to the target object. This lets you turn a function object that takes two arguments into a function object that takes one argument, with a fixed value for its other argument.


Section 10.1. Placeholders

10.1. Placeholders

namespace std {
  namespace tr1 {
    namespace placeholders {
    extern unspecified _1;
    extern unspecified _2;
    extern unspecified _3;
} } }

Placeholder types have default constructors and copy constructors that do not throw exceptions. The types are not required to support assignment, but if they do, their assignment operators do not throw exceptions.

As we'll see in the next section, placeholders are passed as arguments to the bind function template to designate argument values that will be supplied later. The placeholders supplied in the TR1 library are named _1, _2, and so on, up to the maximum value supported by the implementation. You can also supply your own placeholders, although you'll probably never need to do this. If you do, see Section 10.3 for an explanation of how to do it.


Section 10.2. unspecified bind(.....)

10.2. unspecified bind(.....)

template <class Fty, class T1, class T2, ..., class TN>
  unspecified bind(Fty fn, T1 t1, T2 t2, ..., TN tn);
template <class Ret,
  class Fty, class T1, class T2, ..., class TN>
  unspecified bind(Fty fn, T1 t1, T2 t2, ..., TN tn);

The first function returns a forwarding call wrapper (see Section 6.1) wrap that has a weak result type (see Section 6.2). Calling wrap(u1, u2, ..., uM) returns INVOKE_R (fn, v1, v2, ..., vn, Ret), where cv represents the cv-qualifiers of wrap, the values v1, v2, ..., vN and their types V1, V2, ..., VN are determined by the rules for bound types, and Ret is the type named by result_of<Fty cv (V1, V2, ..., VN)>::type).

The second function returns a forwarding call wrapper (see Section 6.1) wrap that has a nested type named result_type that is a synonym for the template argument Ret. Calling wrap(u1, u2, ..., uM) returns INVOKE_R (fn, v1, v2, ..., vn, Ret), where cv represents the cv-qualifiers of wrap, and the values v1, v2, ..., vN and their types V1, V2, ..., VN are determined by the rules for bound types.

For both functions, the types Fty, T1, ..., TN must be copy constructible, and a set of values w1, w2, ..., wN must exist for which INVOKE (fn, w1, w2, ..., wN) is a valid expression.

The bound arguments v1, v2, ..., vN and their types V1, V2, ..., VN are determined by the type of the corresponding argument ti and its type Ti in the call to bind and by the cv-qualifiers cv of the call wrapper wrap. The value and type of the argument vi are determined by the first of the following four rules that applies.

  1. If the type of ti is reference_wrapper<T> for some T, the argument vi is ti.get(), and its type Vi is T&.

  2. If the value of std::tr1::is_bind_expression<Ti>::value is true, the argument vi is ti(u1, u2, ..., uM), and its type Vi is result_of<Ti cv (U1&, U2&, ..., UM&)>::type.

  3. If the value j of std::tr1::is_placeholder<Ti>::value is not zero, the argument vi is uj, and its type Vi is Uj&.

  4. Otherwise, the argument vi is ti, and its type Vi is cv Ti&.

That's pretty dense. To sort it out, we'll look at the additional arguments to bind, then start at the bottom of the list of rules and work our way up to the top. Keep in mind that three calls and three corresponding argument lists are involved. First is a call to bind, which returns a call wrapper; second is a call to that call wrapper, which provides additional arguments that can be referred to by placeholder arguments in the call to bind; and third is a call to the call wrapper's target object, made by the call wrapper. The types of the arguments in the call to bind determine how those arguments are treated and, sometimes, how the arguments in the call to the call wrapper are treated.

10.2.1. Additional Arguments to bind

Every call to bind must have one argument that is a callable object and as many additional arguments as are needed to call that callable object.

Example 10.2. Additional Arguments (funobjbind/additional.cpp)

#include <functional>
using std::tr1::bind;

int no_args()
  { // function taking no arguments
  return 1;
  };

struct one_arg
  { // class type with member operator() taking one argument
  int operator()(int i) const
    { // function call operator that takes one argument
    return i;
    }
  typedef int result_type;
  };

struct three_args
  { // class type with member function taking two arguments
  int f(int i, int j) const
    {  // member function taking two arguments
    return i + j;
    }
  };

void call_bind()
  { // examples of calls to bind
  // no additional arguments
  bind(no_args);

  // one additional argument
  one_arg a1;
  bind(a1, 1);

  // three additional arguments

  three_args a3;
  bind(&three_args::f, a3, 1, 2);
  }

In this example, the first call to bind passes a single argument that is a pointer to the function no_args. Because no_args takes no arguments, the call to bind is made with no additional arguments. The second call to bind passes a callable object of type one_arg. Since one_arg's function call operator takes one argument, the call to bind has one additional argument. The third call to bind passes an argument that is a pointer to a member function of the class three_args. In order to call the member function, we need one argument that designates the object for the member function and as many more additional arguments as there are arguments to the member function. Since three_-args::f takes two arguments, the call to bind must have three additional arguments: the object and the two arguments for three_args::f.

10.2.2. Ordinary Arguments

Under rule 4, arguments that are ordinary types are simply passed to the target object when the bind object is called.

Example 10.3. Rule 4 (funobjbind/rule4.cpp)

#include <iostream>
#include <functional>
using std::tr1::bind;
using std::cout;

int no_args()
  {   // function taking no arguments
  return 0;
  };

struct one_arg
  {   // class type with member operator() taking one argument
  int operator()(int i) const
    {   // function call operator that takes one argument
    return i;
    }
  typedef int result_type;
  };

struct three_args
  {   // class type with member function taking two arguments
  three_args(int v) : val(v) {}
  int f(int i, int j) const
    {    // member function taking two arguments
    return val + 2 * i + 3 * j;
    }
private :
  int val;
  };

int main()
  {   // examples of calls to bind
  // no additional arguments
  cout << bind(no_args)() << '\n';
  cout << no_args() << '\n';    // equivalent call

  // one additional argument
  one_arg a1;
  cout << bind(a1, 1)() << '\n';
  cout << a1(1) << '\n';        // equivalent call

  // three additional arguments
  three_args a3(1);
  cout << bind(&three_args::f, a3, 2, 3)() << '\n';
  cout << a3.f(2, 3) << '\n';   // equivalent call
  return 0;
  }

In this example, the three calls to bind are the same as the calls in the previous example. The main difference here is that the object returned by each of those calls to bind is then called with no arguments. Calling the returned object in turn calls the target object, passing the arguments given in the original call to bind.

The first call to bind passes the function pointer no_args. The returned object holds a copy of that pointer. Calling the returned object simply calls no_args, which returns the value 0. The returned object's function call operator returns that value, so the program displays the value 0 for this operation.

The second call to bind passes a callable object of type one_arg and the value 1. The returned object holds a copy of the callable object and of the additional argument: in this case, 1. Calling the returned object in turn calls the target object of type one_arg with the stored value 1. The call to the target object returns its argument, and the call of the returned object also returns that value, so the program displays the value 1 for this operation.

The third call to bind passes a pointer to member function, &three_args::f, followed by an object of type three_args and the values 2 and 3. The returned object holds a copy of each of those four arguments. Calling the returned object calls a.f(2, 3), where a is the stored copy of the object of type tHRee_args. That member function call returns the value 14, so the call of the returned object also returns 14. The program displays the value 14 for this operation.

10.2.3. Placeholder Arguments

Under rule 3, if std::tr1::is_placeholder<Ti>::value is not zero, the value passed to the target object as the argument at position i is the value passed in the call to the bind object as the argument at position is_place-holder<Ti>::value. For the standard placeholders _1, _2, and so on, the corresponding values of is_placeholder::value are 1, 2, and so on. So the placeholder _1 says to pass the first argument, _2 says to pass the second argument, and so on. For example:

bind(f, _1)(a, b)        // calls f(a)
bind(f, _2)(a, b)        // calls f(b)
bind(g, _1, _2)(a, b)    // calls g(a, b)
bind(g, _2, _1)(a, b)    // calls g(b, a)
bind(g, c, _1)(a, b)     // calls g(c, a)

In real code:

Example 10.4. Rule 3 (funobjbind/rule3.cpp)

#include <iostream>
#include <functional>
using std::tr1::bind;
using namespace std::tr1::placeholders;
using std::cout;

struct one_arg
  { // class type with member operator() taking one argument
  int operator()(int i) const
    { // function call operator that takes one argument
    return i;
    }
  typedef int result_type;
  };

struct three_args
  { // class type with member function taking two arguments
  three_args(int v) : val(v) {}
  int f(int i, int j) const
    {   // member function taking two arguments
    return val + 2 * i + 3 * j;
    }
private :
  int val;
  };

int main()
  { // examples of calls to bind
  // argument values
  int a = 10;
  int b = 11;
  int c = 12;

  // one additional argument
  one_arg a1;
  cout << bind(a1, _1)(a, b, c) << '\n';
  cout << a1(a) << '\n';          // equivalent call
  cout << bind(a1, _2)(a, b, c) << '\n';
  cout << a1(b) << '\n';          // equivalent call
  cout << bind(a1, _3)(a, b, c) << '\n';
  cout << a1(c) << '\n';          // equivalent call
  cout << bind(a1, 10)( a, b, c) << '\n';
  cout << a1(10) << '\n';         // equivalent call

  // three additional arguments
  three_args a3(1);
  cout << bind(&three_args::f, a3, _1, _2)(a, b, c)
    << '\n';
  cout << a3.f(a, b) << '\n';     // equivalent call
  cout << bind(&three_args::f, a3, _2, _3)(a, b, c)
    << '\n';
  cout << a3.f(b, c) << '\n';     // equivalent call
  cout << bind(&three_args::f, a3, _3, _2)(a, b, c)
    << '\n';
  cout << a3.f(c, b) << '\n';     // equivalent call
  cout << bind(&three_args::f, a3, 1, _2)(a, b, c)
    << '\n';
  cout << a3.f(1, b) << '\n';     // equivalent call
  return 0;
  }

You probably noticed in both of the preceding code examples that the call to the object returned by bind used named variables, not literals. That's because rule 3 says that the declared type of the argument to the function call operator is Uj&. In this example, all the Ujs are of type int, so the argument types are all int&s. That's fine for named variables of type int but leads to a problem for literals, because you can't pass a literal value where an int& is expected.[2] This is an example of what is known as the forwarding problem: It's very difficult to write a function template that passes its arguments by reference to another function. The problem arises because template arguments of type T and of type const T are both treated by the compiler as T. Ordinarily, that's what you want: You should be able to call a function that takes an argument of type int with the value 1, even though the type of 1 is const int. But when you want to use a reference to the type, const matters. The rule in the TR1 library is that you get a non-const reference, and there's a suggestion that implementations ought to try to support const references as well. Unfortunately, doing so in standard C++ requires multiple overloads:

[2] More generally, the problem arises for all rvalues. A value defined by the expression int() also can't be passed by reference.

void f(int&, int&);
void f(const int&, int&);
void f(int&, const int&);
void f(const int&, const int&);

This, in turn, requires multiple function templates, one for each combination of const and non-const arguments. The number of overloads needed is 2n, where n is the number of arguments. Obviously, this becomes prohibitive as n becomes larger. So don't count on being able to call bind objects with constant values.[3]

[3] Language changes could make it easier to write these function templates. If those changes are made, you can expect bind, reference_wrapper, and mem_fn to take advantage of them.

10.2.4. bind Arguments

Under rule 2, arguments to bind can themselves be objects returned by calls to bind. For example:

bind(f, bind(g, a), b)(c, d)    // calls f(g(a), b)
bind(f, bind(g, b), _1)(c, d)   // calls f(g(b), c)

Any placeholder arguments in nested calls to bind refer to the arguments in the innermost call to a bind object that contains the placeholder. For example:

bind(f, bind(g, _1), a)(c, d)             // calls f(g(c), a)
bind(f, bind(g, _1), _2)(c, d)            // calls f(g(c), d)
bind (f, bind(g, _2)(a, b), _2)(c, d)     // calls f(g(b), d)

In real code:

Example 10.5. Rule 2 (funobjbind/rule2.cpp)

#include <iostream>
#include <functional>
using std::tr1::bind;
using namespace std::tr1::placeholders;
using std::cout;

struct one_arg
  { // class type with member operator() taking one argument
  int operator()(int i) const
    { // function call operator that takes one argument
    return i;
    }
  typedef int result_type;
  };

struct three_args
  { // class type with member function taking two arguments
  three_args(int v) : val(v) {}
  int f(int i, int j) const
    {   // member function taking two arguments
    return val + 2 * i + 3 * j;
    }
private :
  int val;
  };

int main()
  { // examples of calls to bind
  // argument values
  int a = 10;
  int b = 11;
  int c = 12;
  one_arg a1;
  one_arg a2;
  three_args a3(2);

  // no additional arguments
  cout << bind(a1, bind(a2, a))() << '\n';
  cout << a1(a2(a)) << '\n';            // equivalent call
  // one additional argument
  cout << bind(a1, bind(a2, _1))(b) << '\n';
  cout << a1(a2(b)) << '\n';            // equivalent call

  // two additional arguments
  cout << bind(a1, bind(a2, _1))(a, b) << '\n';
  cout << a1(a2(a)) << '\n';             // equivalent call
  cout << bind(&three_args::f, a3,
    bind(a1, _1), bind(a2, _1))(a, b) << '\n';
  cout << a3.f(a1(a), a2(a)) << '\n';    // equivalent call

  return 0;
  }

10.2.5. reference_wrapper Arguments

Under rule 1, arguments to bind can be objects of type reference_wrap-per<Ty>. In this case, the argument passed to the target object is passed by reference rather than by value.

Example 10.6. Rule 1 (funobjbind/rule1.cpp)

#include <functional>
#include <iostream>
using std::tr1::bind; using std::tr1::ref;
using std::cout;

void modify(int& arg)
  {  // add 1 to argument
  ++arg;
  }

int main()
  {   // demonstrate use of reference_wrapper with bind
  int i = 0;
  cout << i << '\n';

  // i passed by value; not modified
  bind(modify, i)();
  cout << i << '\n';

  // i passed by reference; modified
  bind(modify, ref(i))();
  cout << i << '\n';
  return 0;
  }

In the first call to bind, the argument i is passed directly. Its value is copied into the callable object returned by bind, and that copy is passed to modify when the callable object is called. Because modify is passed a copy of i, the original value of i is not changed.

In the second call to bind, the argument i is wrapped in a reference_-wrapper object by the call to ref. The callable object returned by bind holds a reference to i, and that reference is passed in the call to modify. The value of i is changed by the call to modify.


Section 10.3. Extending bind

10.3. Extending bind

template <class Ty> struct is_placeholder {
  static const int value;
  };
template <class Ty> struct is_bind_expression {
  static const bool value;
  };

As mentioned earlier, bind determines whether an argument of type Arg is a placeholder by examining is_placeholder<Arg>::value. If its value is zero, the argument is not a placeholder; if its value is nonzero the value indicates which argument the placeholder refers to. Similarly, is_bind_expression<Arg>::value is true if Arg is a bind expression.

These templates can be specialized for types defined in your code.[4] In particular, if you're using another template library that binds arguments to callable types, you can pass that library's objects and placeholders to bind if you've provided specializations of is_placeholder and is_bind_expression for that library's types. The call to bind and to the object it returns will then follow rules 2 and 3.

[4] However, adding your own specializations does not change the bind implementation's upper limit on the number of placeholders. So the value you put in the specialization must be greater than zero and less than the upper limit.


Exercises

Exercise 1

For each of the following errors, write a simple test case containing the error, and try to compile it. In the error messages, look for the key words that relate to the error in the code.

  1. Calling bind with a placeholder argument that tries to use an argument that is past the implementation's maximum allowed value.

  2. Calling bind with fewer or more arguments than the callable object takes. (You may have to call the returned object to get an error message.)

  3. Calling an object returned by bind with a literal value instead of an lvalue.

  4. Calling bind with a first argument that is not a callable object. (You may have to call the returned object to get an error message.)

Exercise 2

Write a program that calls bind, passing a pointer to the standard library function cosf and the value 1.0f, and calls the resulting callable object with no arguments. Show the result.

Exercise 3

Write a program that calls bind, passing a pointer to the standard library function cosf and the placeholder _1, and calls the resulting callable object with an argument that is a variable of type float holding the value 1.0f.

Exercise 4

Write a program that calls bind, passing a pointer to the standard library function cosf and the placeholder _2, and calls the resulting callable object with two arguments. The second argument should be a variable of type float holding the value 1.0f.

Exercise 5

Write a program that defines a type named employee with a public member function named ID that takes no arguments and returns a value of type int. The constructor for employee should set the value that will be returned by ID. Create a callable object whose function call operator returns TRue for all employee objects whose ID is greater than 10. This takes two steps: Call bind to bind the member function ID to the employee object that will be passed to the function call operator (use _1 to refer to that object), and call bind again to pass that result and the value 10 to the standard library class template less. Create a TR1 array of employee objects, and use the standard algorithm count_if to count the number of employees whose ID is greater than 10.

Exercise 6

Using the employee type from the previous example, write a program that sorts a standard library vector object that holds employee objects so that the contained objects are in order according to their ID values.


Part IV: Type Traits

    Chapter 11. Type Traits


Chapter 11. Type Traits

I am the voice of today, the herald of tomorrow.... I am the leaden army that conquers the worldI am type.

The Type Speaks
FREDERIC WILLIAM GOUDY

The TR1 library has more than 50 class templates that provide compile-time constants based on various properties of their type arguments or new types that are like their type argument with some of its properties changed. They are basic building blocks. You can use them directly in your code, but more often, you'll use them to construct other templates that do something you need in a more narrowly focused library or in your current application.

As an example, the C++ language allows you to overload functions based on their argument types.[1] In some cases, though, you need a more flexible way to decide which of several functions to call. In Chapter 13, for instance, we'll look at a template member function named seed that does one thing if it is called with a value of an integral type and something else if it is called with a function object. One way to handle this overloading would be to write a separate overloaded function for each of the nine standard integral types and a function template to handle all other argument types:

[1] The header <cmath>, for example, provides three versions of the function named abs: one that takes an argument of type double, one that takes float, and one that takes long double. When code calls this function, the compiler looks at the type of the argument that is being passed and determines from that which version of the function to call.

Example 11.1. Dispatch with Overloading (typetraits/seedover.cpp)

# include <iostream>
# include <typeinfo>
# include <random>
using std :: cout;

template <class Ty>
void seed_integral (Ty val)
  { // seed with an integral type

  cout << "Called integral version of seed,"
       << " with argument type "
       << typeid(Ty).name() << '\n';
  }

template <class Ty>
void seed_object(Ty val)
  { // seed with a nonintegral type
  cout << "Called nonintegral version of seed,"
       << " with argument type "
       << typeid(Ty).name() << ' \n ' ;
  }

    // dispatch to seed_integral for integral types
void seed(char val) { seed_integral(val); }
void seed(unsigned char val) { seed_integral(val); }
void seed(signed char val) { seed_integral(val); }
void seed(short val) { seed_integral(val); }
void seed(unsigned short val) { seed_integral(val); }
void seed(int val) { seed_integral(val); }
void seed(unsigned int val) { seed_integral(val); }
void seed(long val) { seed_integral(val); }
void seed(unsigned long val) { seed_integral(val); }

    // dispatch to seed_object for nonintegral types
template <class Ty>
void seed(Ty val) { seed_object(val); }

int main()
  { // call seed with several argument types
  seed(1);
  seed('a');
  seed(std ::tr1 :: mt19937 ());
  return 0;
  }

However, if your compiler provides the C99 integral types long long and unsigned long long, this code is wrong: It will call seed_object instead of seed_integral when called with an argument of either of those types. The C++ standard doesn't require these types, though, so if you want to make this code robust, you need to provide overloads for long long and unsigned long long only when you're using a compiler that supports them. Since there's no standard way of identifying those compilers, you have to write additional code to somehow indicate whether to provide these overloads. This kind of problem is more easily solved in a compiler-specific library than on the fly in your code, because the library writer knows the details of the compiler that the library targets. With the addition of a library class template named is_integral, the same problem can be solved with much less repetition.[2]

[2] Strictly speaking, less visible repetition. The obvious implementation of the class template is_integral provides a specialization for each integral type, so the repetition is in the library code. That's a big improvement over writing all the overloads wherever you need them; in addition, if the compiler provides a way of asking about type properties, is_-integral can ask the compiler, with no need to list all the possible integral types.

Example 11.2. Dispatch with Type Traits (typetraits/seedtrait.cpp)

#include <type_traits>
#include <iostream>
#include <typeinfo>
#include <random>
using std::tr1::is_integral;
using std::tr1::true_type; using std::tr1::false_type;
using std::cout;

template <class Ty>
void seed_impl(Ty val, const true_type&)
  { // seed with an integral type
  cout << "Called integral version of seed,"
  cout << " with argument type "
       << typeid(Ty).name() << '\n';
  }

template <class Ty>
void seed_impl(Ty val, const false_type&)
  { // seed with a non-integral type
  cout << "Called non-integral version of seed,"
  cout << " with argument type "
       << typeid(Ty).name() << '\n';
  }

template <class Ty>
void seed(Ty val)
  { // dispatch to appropriate version of seed_impl
  seed_impl(val, is_integral <Ty>());
  }

int main()

  { // call seed with several argument types
  seed(1);
  seed('a');
  seed(std::tr1::mt19937());
  return 0;
  }

This code works because an instantiation of std::tr1::is_integral for an integral type is derived from the type std::tr1::true_type, and an instantiation for any other type is derived from the type std::tr1::false_-type. When it calls seed_impl, seed passes an object is_integral<Ty>(), and the compiler chooses the version of seed_impl whose second argument matches the base type of that object.


Section 11.1. The Header <type_traits>

11.1. The Header <type_traits>

The header <type_traits> provides a class template named integral_constant that holds a compile-time constant value supplied as one of its template arguments. The header also provides two typedefsTRue_type and false_-typethat are specializations of integral_constant holding the Boolean values true and false, respectively.

The header also provides 53 class templates that deal in various ways with their type arguments. These templates are broadly categorized as type predicates, type queries, and type transformations. A type predicate is derived from the type true_type if the condition that it tests is true or from false_type if the condition is false. Most of the type predicates in the TR1 library take a single type argument and give you information about that type. Some take two type arguments and give you information about the relationship between the two types. A type query is derived from a specialization of integral_constant and provides the numeric value of the property being queried. A type transformation has a nested typedef that is a synonym for the type passed as the type argument to the template, modified according to the particular transformation.

The TR1 library specification defines some technical terms that describe the interface to various kinds of type traits. These terms are shorthand for a set of properties and can make it easier to describe the requirements for code that uses various type traits.[3]

[3] These terms, however, aren't used anywhere else in the TR1 library specification.

A UnaryTypeTrait is a class template that takes one template type argument and, if necessary, additional arguments that more fully define the property being described. It must be default constructible and must be derived, directly or indirectly, from a specialization of integral_constant. In the TR1 library, each of the type predicates that takes one argument and each of the type queries meet the requirements for a UnaryTypeTrait.

A BinaryTypeTrait is just like a UnaryTypeTrait but takes two type arguments. In the TR1 library, each of the type predicates that take two arguments meets the requirements for a BinaryTypeTrait.

A TransformationTypeTrait is a class template that takes one template type argument and, if necessary, additional arguments that more fully define the modification. The class template defines a nested type named type that is a synonym for the modified type. In the TR1 library, each of the type transformations satisfies the requirements for a TransformationTypeTrait.

Some of the specifications include a paragraph beginning with the words "An implementation may ...". This phrase introduces a compromise rule, imposed by the need to implement the TR1 library without help from the compiler. Some of the type predicates can't be written without such help, so the specification allows them to give incorrect information in certain specific ways. These compromise rules have been carefully formulated, so that in most cases, the incorrect information won't affect the correctness of your code.[4] Be sure, though, that you understand the weaker form of the predicate before you use it.

[4] In most cases, these predicates are used to choose optimizations; the unoptimized version works but is slower.

namespace std {
 namespace tr1 {

     // HELPER TYPES (Section 11.2)
template < class Ty, Ty val > struct integral_constant;
typedef integral_constant < bool, false > false_type ;
typedef integral_constant < bool, true > true_type;

     // PRIMARY TYPE CATEGORIES (Section 11.3)
template < class Ty > struct is_void ;
template < class Ty > struct is_integral ;
template < class Ty > struct is_floating_point ;
template < class Ty > struct is_array ;
template < class Ty > struct is_pointer;
template < class Ty > struct is_reference;
template < class Ty > struct is_member_object_pointer;

template < class Ty > struct is_member_function_pointer;
template < class Ty > struct is_enum;
template < class Ty > struct is_union;
template < class Ty > struct is_class;
template < class Ty > struct is_function;

    // COMPOSITE TYPE CATEGORIES (Section 11.4)
template < class Ty > struct is_arithmetic;
template < class Ty > struct is_fundamental;
template < class Ty > struct is_object;
template < class Ty > struct is_scalar;
template < class Ty > struct is_compound;
template < class Ty > struct is_member_pointer;

     // TYPE PROPERTIES (Section 11.5)
template < class Ty > struct is_const;
template < class Ty > struct is_volatile;
template < class Ty > struct is_pod;
template < class Ty > struct is_empty;
template < class Ty > struct is_polymorphic;
template < class Ty > struct is_abstract;
template < class Ty > struct has_trivial_constructor;
template < class Ty > struct has_trivial_copy;
template < class Ty > struct has_trivial_assign;
template < class Ty > struct has_trivial_destructor;
template < class Ty > struct has_nothrow_constructor;
template < class Ty > struct has_nothrow_copy;
template < class Ty > struct has_nothrow_assign;
template < class Ty > struct has_virtual_destructor;
template < class Ty > struct is_signed;
template < class Ty > struct is_unsigned;
template < class Ty > struct rank;
template < class Ty, unsigned I = 0 > struct extent;

     // TYPE RELATIONSHIPS (Section 11.6)
template < class Ty1, class Ty2 > struct is_same;
template < class From, class To > struct is_convertible;
template < class Base, class Derived > struct is_base_of;

     // TYPE TRANSFORMATIONS (Section 11.7)
template < class Ty > struct remove_const;
template < class Ty > struct remove_volatile;
template < class Ty > struct remove_cv;
template < class Ty > struct add_const;
template < class Ty > struct add_volatile;
template < class Ty > struct add_cv;
template < class Ty > struct remove_reference;
template < class Ty > struct add_reference;
template < class Ty > struct remove_pointer;
template < class Ty > struct add_pointer;
template < class Ty > struct remove_extent;
template < class Ty > struct remove_all_extents;

     // ALIGNMENT (Section 11.8)
template < class Ty > struct alignment_of;
template < size_t Len, size_t Align > struct aligned_storage;

} };


Section 11.2. Helper Types

11.2. Helper Types

template < class Ty, Ty val > struct integral_constant {
  static const Ty value = val ;
  typedef Ty value_type ;
  typedef integral_constant <Ty, val > type ;
};
typedef integral_constant < bool, true > true_type ;
typedef integral_constant < bool, false > false_type ;

The static member value is an integral constant expression whose value is the template argument val.

The type integral_constant<Ty, val>::value_type is a synonym for the template type argument Ty.

The type integral_constant<Ty, val>::type is a synonym for the type of the template instantiation, integral_constant<Ty, val>.

The type TRue_type is a synonym for template specialization integral_-constant<bool, true>.

The type false_type is a synonym for the template specialization integral_constant<bool, false>.

The class template integral_constant holds a value that is an integral constant expression. Integral constant expressions are often called compile-time constants because they can be used to provide values, such as the number of elements in an array declaration, the number of bits in a bitfield, or the value of a case label, that must be known at compile time. In addition, because the stored value is passed as a template argument, template instantiations that hold different values are different types. This makes it possible to choose among overloaded functions based on values, as we saw in the previous example.

The two typedefs true_type and false_type are integral_constant specializations that hold Boolean values. They provide base classes for the unary type traits and the binary type traits, each of which tells you whether a type or a pair of types has a certain property.


Section 11.3. Primary Type Categories

11.3. Primary Type Categories

Each of these class templates defines a type predicate. The templates remove any top-level const or volatile qualifiers from their type argument Ty and then determine whether the resulting type belongs to the template's type category. These type categories are defined in the C++ Standard in Section 3.9 [basic.types]. The categories are complete and mutually exclusive: for any type Ty, exactly one of these type predicates will be true.

template < class Ty > struct is_void;

The template specialization is_void<Ty> is derived from TRue_type if the type Ty is a cv-qualified form of void. Otherwise, it is derived from false_type.

template < class Ty > struct is_integral;

The template specialization is_integral<Ty> is derived from TRue_type if the type Ty is a cv-qualified form of an integral type. Otherwise, it is derived from false_type.

An integral type is one of char, unsigned char, signed char, short, unsigned short, int, unsigned int, long, and unsigned long. If a compiler supports them, the C99 types long long and unsigned long long are also integral types.

template < class Ty > struct is_floating_point;

The template specialization is_floating_point<Ty> is derived from TRue_type if the type Ty is a cv-qualified form of a floating-point type. Otherwise, it is derived from false_type.

A floating-point type is one of float, double, and long double.

template < class Ty > struct is_array;

The template specialization is_array<Ty> is derived from true_type if the type Ty is a cv-qualified form of an array type. Otherwise, it is derived from false_type.

The class template array (see Chapter 4) is not an array type.

template < class Ty > struct is_pointer;

The template specialization is_pointer<Ty> is derived from true_type if the type Ty is a cv-qualified form of a pointer type. Otherwise, it is derived from false_type.

This predicate is true for ordinary pointer types but not for pointers to members.

template < class Ty > struct is_reference;

The template specialization is_reference<Ty> is derived from true_-type if the type Ty is a cv-qualified form of a reference type. Otherwise, it is derived from false_type.

template < class Ty > struct is_member_object_pointer;

The template specialization is_member_object_pointer<Ty> is derived from TRue_type if the type Ty is a cv-qualified form of pointer to data member. Otherwise, it is derived from false_type.

template < class Ty > struct is_member_function_pointer;

The template specialization is_member_function_pointer<Ty> is derived from true_type if the type Ty is a cv-qualified form of pointer to member function. Otherwise, it is derived from false_type.

template < class Ty > struct is_enum;

The template specialization is_enum<Ty> is derived from true_type if the type Ty is a cv-qualified form of an enumeration type. Otherwise, it is derived from false_type.

template < class Ty > struct is_union;

The template specialization is_union<Ty> is derived from true_type if the type Ty is a cv-qualified form of a union type. Otherwise, it is derived from false_type.

An implementation may define this template as template <class Ty> struct is_union {}.

This template's compromise rule means that code that uses is_union to determine whether a type is a union typeby looking for one of the base types true_type or false_typewill produce a diagnostic if is_union is not supported.

template < class Ty > struct is_class;

The template specialization is_class<Ty> is derived from true_type if the type Ty is a cv-qualified form of a class type but not a union type. Otherwise, it is derived from false_type.

An implementation may define this template as template <class Ty> struct is_class {}.

This template's compromise rule means that code that uses is_class to determine whether a type is a class typeby looking for one of the base types true_type or false_typewill produce a diagnostic if is_class is not supported.

template < class Ty > struct is_function;

The template specialization is_function<Ty> is derived from true_type if the type Ty is a cv-qualified form of a function type. Otherwise, it is derived from false_type.

Note that this predicate detects function types, not pointers to functions. As we saw in Chapter 9, a function type is a return type followed by a left parenthesis followed by a possibly empty argument list followed by a right parenthesis.


Section 11.4. Composite Type Categories

11.4. Composite Type Categories

Each of these class templates defines a type predicate. The templates remove any top-level const or volatile qualifiers from their type argument Ty and then determine whether the resulting type belongs to the template's type category. Defined in various places in the C++ standard, these type categories are referred to as composite because they can be composed from the primary predicates discussed in Section 11.3.

template < class Ty > struct is_arithmetic;

The template specialization is_arithmetic<Ty> is derived from TRue_-type if the type Ty is a cv-qualified form of an arithmetic type. Otherwise, it is derived from false_type.

An arithmetic type is an integral type or a floating-point type.

template < class Ty > struct is_fundamental;

The template specialization is_fundamental<Ty> is derived from TRue_-type if the type Ty is a cv-qualified form of a fundamental type. Otherwise, it is derived from false_type.

A fundamental type is an integral type, a floating-point type, or the type void.

template < class Ty > struct is_object;

The template specialization is_object<Ty> is derived from true_type if the type Ty is a cv-qualified form of an object type. Otherwise, it is derived from false_type.

An object type is any type that is not a function type, not a reference type, and not void.

template < class Ty > struct is_scalar;

The template specialization is_scalar<Ty> is derived from TRue_type if the type Ty is a cv-qualified form of a scalar type. Otherwise, it is derived from false_type.

A scalar type is an arithmetic type, an enumeration type, a pointer type, or a pointer to member type.

template < class Ty > struct is_compound;

The template specialization is_compound<Ty> is derived from true_type if the type Ty is a cv-qualified form of a compound type. Otherwise, it is derived from false_type.

A compound type is a type that is not a fundamental type.

template < class Ty > struct is_member_pointer;

The template specialization is_member_pointer<Ty> is derived from true_type if the type Ty is a cv-qualified form of a pointer to member. Otherwise, it is derived from false_type.

A member pointer is a pointer to member function or a pointer to member data.


Section 11.5. Type Properties

11.5. Type Properties

The class templates rank and extent define type queries. All the other class templates define type predicates. They provide information about properties of their type argument Ty.

template < class Ty > struct is_const;

The template specialization is_const<Ty> is derived from TRue_type if the type Ty has a top-level const qualifier. Otherwise, it is derived from false_type.

template < class Ty > struct is_volatile;

The template specialization is_volatile<Ty> is derived from TRue_type if the type Ty has a top-level volatile qualifier. Otherwise, it is derived from false_type.

template < class Ty > struct is_pod;

The type Ty must be a complete type.

The template specialization is_pod<Ty> is derived from TRue_type if the type Ty is a POD[5] type. Otherwise, it is derived from false_type.

An implementation may define this template by deriving from false_-type or TRue_type without regard to the properties of the type argument Ty, except that the following assertions shall be true:

[5] Plain old data. If you want the exact details of its definition, you'll have to dig through the C++ standard.

is_pod <Ty>:: value  >=
  (is_scalar <Ty>:: value ||  is_void <Ty>:: value)
is_pod <Ty >:: value  == is_pod <const Ty>:: value
is_pod <Ty >:: value  == is_pod <volatile Ty>:: value
is_pod <Ty >:: value  ==
  is_pod < remove_extent <Ty>:: type>:: value

Generally speaking, a POD is any data type whose bits alone determine its value. In particular, POD types can be copied with memcpy, so when you need to copy an array of objects of POD type, you can use memcpy on the entire array rather than assigning elements one at a time.

This template's compromise rule means that all cv-qualified forms[6] of all scalar types (and the type void) are PODs and that arrays of PODs are also PODs. Thus, when it tells you that a type is a POD, it will be correct; when it tells you that a type is not a POD, it will sometimes be wrong.

[6] The wording in TR1 doesn't quite say that, but that's the intention.

template < class Ty > struct is_empty;

The type Ty must be a complete type.

The template specialization is_empty<Ty> is derived from TRue_type if the type Ty is an empty type. Otherwise, it is derived from false_type.

An implementation may define this template by deriving from false_type or true_type without regard to the properties of the type argument Ty.

This template's compromise rule implies that you cannot use is_empty in portable code. Although that's technically true, the intention was to allow is_empty<Ty> to be derived from false_type even if the type Ty is empty but not to allow it to be derived from TRue_type if Ty is not empty. Under this rule, is_empty<Ty>::value can be used to trigger optimizations that depend on a type being empty. When the result is wrong, the code that uses it will still be correct but won't get the optimization. It's probably safe to assume that implementations will follow this more restrictive rule.

template < class Ty > struct is_polymorphic;

The type Ty must be a complete type.

The template specialization is_polymorphic<Ty> is derived from TRue_-type if the type Ty is a polymorphic type. Otherwise, it is derived from false_type.

An implementation may define this template as template <class Ty> struct is_polymorphic {}.

A polymorphic type is a class type with at least one virtual function.

This template's compromise rule means that code that uses is_polymorphic to determine whether a type is polymorphicby looking for one of the base types true_type or false_typewill produce a diagnostic if is_polymorphic is not supported.

template < class Ty > struct is_abstract;

The type Ty must be a complete type.

The template specialization is_abstract<Ty> is derived from true_type if the type Ty is an abstract type. Otherwise, it is derived from false_-type.

An implementation may define this template as template <class Ty> struct is_abstract {}.

An abstract class is one with at least one pure virtual function. Abstract classes are used to define the interface to a family of types defined by derived classes that override virtual functions, both ordinary and pure, in the abstract base type.

This template's compromise rule means that code that uses is_abstract to determine whether a class is abstractby looking for one of the base types true_type or false_typewill produce a diagnostic if is_abstract is not supported.

template < class Ty > struct has_trivial_constructor;

The type Ty must be a complete type.

The template specialization has_trivial_constructor<Ty> is derived from true_type if the default constructor for the type Ty is trivial. Otherwise, it is derived from false_type.

An implementation may define this template by deriving from false_-type or true_type without regard to the properties of the type argument Ty, except that the following assertions shall be true:

has_trivial_constructor <Ty>:: value >=
  is_pod <Ty >:: value
has_trivial_constructor <Ty>:: value ==
  has_trivial_constructor <remove_extent <Ty>:: type>
    :: value

A trivial default constructor is an implicitly declared default constructor for a class that has no virtual functions and no virtual base classes, whose direct base classes all have trivial default constructors, and whose non-static data members of class type all have trivial default constructors. Classes with trivial default constructors don't require initialization. Classes that do not have trivial default constructors can't be used as members of unions.

This template's compromise rule implies that you cannot use has_trivial_constructor in portable code. Although that's technically true, the intention was to allow implementations to derived has_trivial_constructor<Ty> from false_type even if the type Ty has a trivial constructorexcept in the special cases enumerated in the compromise rulebut not to allow it to be derived from TRue_type if Ty does not have a trivial constructor. Under this rule, has_trivial_constructor<Ty>::value can be used to trigger optimizations that depend on a type having a trivial constructor. When the result is wrong, the code that uses it will still be correct but won't get the optimization. It's probably safe to assume that implementations will follow this more restrictive rule.

template < class Ty > struct has_trivial_copy;

The type Ty must be a complete type.

The template specialization has_trivial_copy<Ty> is derived from the class TRue_type if the copy constructor for the type Ty is trivial. Otherwise, it is derived from false_type.

An implementation may define this template by deriving from false_-type or true_type without regard to the properties of the type argument Ty, except that the following assertions shall be true:

has_trivial_copy <Ty>:: value>= is_pod <Ty>:: value
has_trivial_copy <Ty>:: value ==
  has_trivial_copy < remove_extent <Ty>:: type>:: value

A trivial copy constructor is an implicitly declared copy constructor for a class that has no virtual functions and no virtual base classes, whose direct base classes all have trivial copy constructors, and whose non-static data members of class type all have trivial copy constructors. Classes that have trivial copy constructors can be copy constructed by copying their bits, typically with memcpy. Classes that do not have trivial copy constructors can't be used as members of unions.

This template's compromise rule implies that you cannot use has_trivial_copy in portable code. Although that's technically true, the intention was to allow has_trivial_copy<Ty> to be derived from false_type even if the type Ty has a trivial copy constructorexcept in the special cases enumerated in the compromise rulebut not to allow it to be derived from TRue_type if Ty does not have a trivial copy constructor. Under this rule, has_trivial_-copy<Ty>::value can be used to trigger optimizations that depend on a type having a trivial copy constructor. When the result is wrong, the code that uses it will still be correct but won't get the optimization. It's probably safe to assume that implementations will follow this more restrictive rule.

template < class Ty > struct has_trivial_assign;

The type Ty must be a complete type.

The template specialization has_trivial_assign<Ty> is derived from true_type if the assignment for the type Ty is trivial. Otherwise, it is derived from false_type.

An implementation may define this template by deriving from false_-type or true_type without regard to the properties of the type argument Ty, except that the following assertions shall be true:

has_trivial_assign <Ty>:: value>= is_pod <Ty>:: value
has_trivial_assign <Ty>:: value ==
  has_trivial_assign <remove_extent <Ty>:: type>:: value

A trivial copy assignment operator is an implicitly declared copy assignment operator for a class that has no virtual functions and no virtual base classes, whose direct base classes all have trivial copy assignment operators, and whose non-static data members of class type all have trivial copy assignment operators. Classes that have trivial copy assignment operators can be copied by copying their bits, typically with memcpy. Classes that do not have trivial copy assignment operators can't be used as members of unions.

This template's compromise rule implies that you cannot use has_trivial_assign in portable code. Although that's technically true, the intention was to allow has_trivial_assign<Ty> to be derived from false_type even if the type Ty has a trivial copy assignment operatorexcept in the special cases enumerated in the compromise rulebut not to allow it to be derived from true_type if Ty does not have a trivial copy assignment operator. Under this rule, has_trivial_assign<Ty>::value can be used to trigger optimizations that depend on a type having a trivial copy assignment operator. When the result is wrong, the code that uses it will still be correct but won't get the optimization. It's probably safe to assume that implementations will follow this more restrictive rule.

template < class Ty > struct has_trivial_destructor;

The type Ty must be a complete type.

The template specialization has_trivial_destructor<Ty > is derived from true_type if the destructor for the type Ty is trivial. Otherwise, it is derived from false_type.

An implementation may define this template by deriving from false_-type or TRue_type without regard to the properties of the type argument Ty, except that the following assertions shall be true:

has_trivial_destructor <Ty>:: value>= is_pod <Ty>:: value
has_trivial_destructor <Ty>:: value ==
  has_trivial_destructor <remove_extent <Ty>:: type>
    :: value

A trivial destructor is an implicitly declared destructor for a class whose direct base classes all have trivial destructors and whose non-static data members of class type all have trivial destructors. Classes that have trivial destructors do not need to be destroyed. Classes that do not have trivial destructors can't be used as members of unions.

This template's compromise rule implies that you cannot use has_trivial_destructor in portable code. Although that's technically true, the intention was to allow has_trivial_destructor<Ty> to be derived from false_-type even if the type Ty has a trivial destructorexcept in the special cases enumerated in the compromise rulebut not to allow it to be derived from true_type if Ty does not have a trivial destructor. Under this rule, has_-trivial_destructor<Ty>::value can be used to trigger optimizations that depend on a type having a trivial destructor. When the result is wrong, the code that uses it will still be correct but won't get the optimization. It's probably safe to assume that implementations will follow this more restrictive rule.

template < class Ty > struct has_nothrow_constructor;

The type Ty must be a complete type.

The template specialization has_nothrow_constructor<Ty> is derived from true_type if the default constructor for the type Ty has a nothrow specifier or if the compiler can otherwise determine that it will not throw an exception. Otherwise, it is derived from false_type.

An implementation may define this template by deriving from false_type or true_type without regard to the properties of the type argument Ty.

This template's compromise rule implies that you cannot use has_nothrow_-constructor in portable code. Although that's technically true, the intention was to allow has_nothrow_constructor<Ty> to be derived from false_type even if the default constructor for the type Ty does not throw exceptions but not to allow it to be derived from true_type if the constructor for Ty does throw exceptions. Under this rule, has_nothrow_constructor<Ty>::value can be used to trigger optimizations that depend on a type's constructor not throwing exceptions. When the result is wrong, the code that uses it will still be correct but won't get the optimization. It's probably safe to assume that implementations will follow this more restrictive rule.

template < class Ty > struct has_nothrow_copy;

The type Ty must be a complete type.

The template specialization has_nothrow_copy<Ty> is derived from the class true_type if the copy constructor for the type Ty has a nothrow specifier or if the compiler can otherwise determine that it will not throw an exception. Otherwise, it is derived from false_type.

An implementation may define this template by deriving from false_type or true_type without regard to the properties of the type argument Ty.

This template's compromise rule implies that you cannot use has_nothrow_-copy in portable code. Although that's technically true, the intention was to allow has_nothrow_copy<Ty> to be derived from false_type even if the copy constructor for the type Ty does not throw exceptions but not to allow it to be derived from TRue_type if the constructor for Ty does throw exceptions. Under this rule, has_nothrow_copy<Ty>::value can be used to trigger optimizations that depend on a type's copy constructor not throwing exceptions. When the result is wrong, the code that uses it will still be correct but won't get the optimization. It's probably safe to assume that implementations will follow this more restrictive rule.

template < class Ty > struct has_nothrow_assign;

The type Ty must be a complete type.

The template specialization has_nothrow_assign<Ty> is derived from TRue_type if the assignment operator for the type Ty has a nothrow specifier or if the compiler can otherwise determine that it will not throw an exception. Otherwise, it is derived from false_type.

An implementation may define this template by deriving from false_type or TRue_type without regard to the properties of the type argument Ty.

This template's compromise rule implies that you cannot use has_nothrow_-assign in portable code. Although that's technically true, the intention was to allow has_nothrow_assign<Ty> to be derived from false_type even if the assignment operator for the type Ty does not throw exceptions but not to allow it to be derived from true_type if the assignment operator for Ty does throw exceptions. Under this rule, has_nothrow_assign<Ty>::value can be used to trigger optimizations that depend on a type's assignment operator not throwing exceptions. When the result is wrong, the code that uses it will still be correct but won't get the optimization. It's probably safe to assume that implementations will follow this more restrictive rule.

template < class Ty > struct has_virtual_destructor;

The type Ty must be a complete type.

The template specialization has_virtual_destructor<Ty > is derived from TRue_type if the destructor for the type Ty is virtual. Otherwise, it is derived from false_type.

An implementation may define this template by deriving from false_type for all type arguments Ty.

This template's compromise rule allows implementations to report that a type does not have a virtual destructor when it, in fact, does. This implies that you should use has_virtual_destructor<Ty>::value only to trigger optimizations that depend on a type having a virtual destructor. When the result is wrong, the code that uses it will still be correct but won't get the optimization.

template < class Ty > struct is_signed;

The template specialization is_signed<Ty> is derived from true_type if the type Ty is a signed integral type. Otherwise, it is derived from false_-type.

template < class Ty > struct is_unsigned;

The template specialization is_unsigned<Ty> is derived from TRue_type if the type Ty is an unsigned integral type. Otherwise, it is derived from false_type.

template < class Ty > struct rank;

The template specialization rank<Ty> is derived from integral_constant<std::size_t, Rank>, where Rank is the number of dimensions of the array type Ty or 0 if Ty is not an array type.

For example, the rank of the type int is 0, the ranks of the types int[] and int[2] are both 1, and the ranks of the types int[][3] and int[2][3] are both 2.

template < class Ty, unsigned Idx = 0 > struct extent;

The template specialization extent<Ty, Idx> is derived from integral_-constant<std::size_t, Dim>, where Dim is the dimension of the Idx th bound of the type Ty.

If the type Ty is not an array type, if its rank is less than Idx, or if Idx == 0 and the type of Ty is array of unknown bound of Ty1, Dim is zero.

For example:

Expression | Note | Value
extent<int,N>::value | for all N | 0
extent<int[],0>::value |  | 0
extent<int[],N>::value | for all N greater than 0 | 0
extent<int[2],0>::value |  | 2
extent<int[2],N>::value | for all N greater than 0 | 0
extent<int[][3],0>::value |  | 0
extent<int[][3],1>::value |  | 3
extent<int[][3],N>::value | for all N greater than 1 | 0
extent<int[2][3],0>::value |  | 2
extent<int[2][3],1>::value |  | 3
extent<int[2][3],N>::value | for all N greater than 1 | 0


Section 11.6. Type Relationships

11.6. Type Relationships

Each of these class templates defines a type predicate. The templates determine whether their two type arguments have the required relationship.

template < class Ty1, class Ty2 > struct is_same;

The template specialization is_same<Ty1, Ty2> is derived from TRue_-type if the types Ty1 and Ty2 are the same type. Otherwise, it is derived from false_type.

template < class From, class To > struct is_convertible;

The type From must be a complete type or void.

The type To must be a complete, non-abstract type or void.

For all types From and To other than void, the template specialization is_convertible<From, To> is derived from TRue_type if there is an unambiguous, publicly accessible conversion from an lvalue of the type From to the type To. If there is an ambiguous conversion or a conversion that is not publicly accessible, the template specialization is ill formed. Otherwise, it is derived from false_type.

For all types Ty, the template specialization is_convertible<Ty, void> is derived from TRue_type.

For all types Ty other than void, the template specialization is_convert-ible<void, Ty> is derived from false_type.

template < class Base, class Derived > struct is_base_of;

The types Base and Derived must be complete types.

The template specialization is_base_of<Base, Derived> is derived from TRue_type if the type Base is the same type as Derived or if the type Base is a base class of Derived. Otherwise, it is derived from false_type.


Section 11.7. Type Transformations

11.7. Type Transformations

Each of these class templates defines a type transformation. The templates have a nested member named type that is the template type argument Ty appropriately transformed.

template < class Ty > struct remove_const;

The template specialization remove_const<Ty> holds a nested type named type that is the type Ty with any top-level const qualifier removed.

template < class Ty > struct remove_volatile;

The template specialization remove_volatile<Ty> holds a nested type named type that is the type Ty with any top-level volatile qualifier removed.

template < class Ty > struct remove_cv;

The template specialization remove_cv<Ty> holds a nested type named type that is the type Ty with any top-level const and volatile qualifiers removed.

template < class Ty > struct add_const;

The template specialization add_const<Ty> holds a nested type named type that is the type Ty if Ty is a reference or function or a type with a top-level const qualifier. Otherwise, it is const Ty.

template < class Ty > struct add_volatile;

The template specialization add_volatile<Ty> holds a nested type named type that is the type Ty if Ty is a reference or function or a type with a top-level volatile qualifier. Otherwise, it is volatile Ty.

template < class Ty > struct add_cv;

The template specialization add_cv<Ty> holds a nested type named type that is the same type as add_volatile< add_const<Ty> >::type.

template < class Ty > struct remove_reference;

The template specialization remove_reference<Ty> holds a nested type named type that is the type Ty1 if the type Ty is Ty1&. Otherwise, it is Ty.

template < class Ty > struct add_reference;

The template specialization add_reference< Ty > holds a nested type named type that is the type Ty& if Ty is not a reference type. Otherwise, it is Ty.

template < class Ty > struct remove_pointer;

The template specialization remove_pointer<Ty> holds a nested type named type that is the type Ty1 if the type Ty is Ty1*. Otherwise, it is Ty.

template < class Ty > struct add_pointer;

The template specialization add_pointer<Ty> holds a nested type named type that is the type Ty* if Ty is not a pointer type. Otherwise, it is Ty.

template < class Ty > struct remove_extent;

The template specialization remove_extent< Ty > holds a nested type named type that is the type Ty1 if the type Ty is Ty1[M]. Otherwise, it is Ty.

For example:

Expression | Type
remove_extent<int>::type | int
remove_extent<int[]>::type | int
remove_extent<int[2]>::type | int
remove_extent<int[][3]>::type | int[3]
remove_extent<int[2][3]>::type | int[3]

template < class Ty > struct remove_all_extents;

The template specialization remove_all_extents<Ty> holds a nested type named type that is the type Ty1 if the type Ty is Ty1[M]...[N]. Otherwise, it is Ty.

For example:

Expression | Type
remove_all_extents<int>::type | int
remove_all_extents<int[]>::type | int
remove_all_extents<int[2]>::type | int
remove_all_extents<int[][3]>::type | int
remove_all_extents<int[2][3]>::type | int


Section 11.8. Alignment

11.8. Alignment

Some hardware architectures impose alignment constraints, requiring that objects of certain types have addresses whose value is a multiple of some small number. In some cases, this is an absolute requirement: Attempting to access data that is not properly aligned causes a hardware fault. In others, it affects program performance: Attempting to access data that is not properly aligned requires additional bus cycles, slowing reading and writing of that data. Since alignment restrictions are imposed by hardware, the small number that defines the required alignment is usually a power of 2: typically, 4, 8, or 16. When we talk about the required alignment for some type, we usually say that it requires, for example, 8-byte alignment. This means that its address must be a multiple of 8.

template <class Ty> struct alignment_of;
template <std::size_t Len, std::size_t Align>
  struct aligned_storage;

The template specialization alignment_of<Ty> is derived from integral_constant<std::size_t, Align>, where Align is the alignment of objects of type Ty.

The argument Ty to the class template alignment_of<Ty> must name a complete type.

The template specialization aligned_storage< Len, Align > holds a nested type named type that names a POD type that can be used as uninitialized storage for an object whose alignment is a divisor of Align and whose size is less than or equal to Len. The value of the template argument Align must be the same as alignment_of<Ty>::value for some type Ty.[7]

[7] This means, in part, that aligned_storage cannot be used to create a typical DMA buffer, which usually must be aligned on a boundary that's a multiple of a fairly large number, such as 16K.

The primary problem that these templates address is the need to create a properly aligned static storage block to use with placement new. This code doesn't necessarily work correctly:

unsigned char data [ sizeof (double)];
double * loc = new (( void *)& data ) double ;
* loc = 1.0;

The problem here is that the array data can usually be aligned at a 1-byte boundarythat is, anywhere in memorywhereas the double* returned by placement new must point to memory that is properly aligned for an object of type double, which often requires a 4-byte or 8-byte boundary. The usual solution to this problem is to use a union of eight to ten fundamental types, in the hope that one of them will require the target platform's worst-case alignment; a data array that can hold an object of that type will then be able to hold any data type. This approach has two drawbacks. First, alignment requirements for some types may be more severe than those of the types included in the union. In that case, those types will probably not be suitably aligned. Second, this approach wastes space for types whose alignment requirements are less severe than the worst case provided by the union. The solution using the TR1 alignment templates looks like this:

aligned_storage < sizeof ( double ),
  alignment_of <double>:: value>:: type data ;
double * loc = new ((void *)& data) double;
* loc = 1.0;

The definition of data in that code is a bit daunting, so let's look at it piece by piece. First, sizeof(double) is the number of bytes needed to represent a value of type double. Second, alignment_of<double>::value is the required alignment for a value of type double. Those two values are passed as the template arguments Len and Align to the class template aligned_-storage. The resulting template instantiation has a nested type named type that has the required size and alignment. By defining data to be an object of that type, we guarantee that data has the required size and alignment. Since that type is a POD, it has a trivial destructor, so running a destructor on data that doesn't make sense won't cause any problems.


Further Reading

  • Modern C++ Design [Ale01] first brought template metaprogramming to the attention of everyday programmers.

  • C++ Template Metaprogramming [AG05] provides a gentler introduction to template metaprogramming.

  • C++ Templates [VJ03] gives the detailed rules for programming with templates.


Exercises

Exercise 1

For each of the following errors, write a simple test case containing the error, and try to compile it. In the error messages, look for the key words that relate to the error in the code.

  1. Attempting to create an instance of integral_constant with a type that is not an integral type

  2. Attempting to create an instance of integral_constant with a value that is not convertible to the integral type

  3. Attempting to create an instance of is_pod with a type argument that is an incomplete type

  4. Attempting to create an instance of is_empty with a type argument that is an incomplete type

  5. Attempting to create an instance of is_polymorphic with a type argument that is an incomplete type

  6. Attempting to create an instance of is_abstract with a type argument that is an incomplete type

  7. Attempting to create an instance of has_trivial_constructor with a type argument that is an incomplete type

  8. Attempting to create an instance of is_convertible with type arguments that are incomplete types

  9. Attempting to create an instance of alignment_of with a type argument that is an incomplete type

  10. Attempting to create an instance of aligned_storage with an Align argument of 17

Exercise 2

Write a program that contains the following typedefs for specializations of integral_constant:

  1. int_0: holds an integral constant of type int whose value is 0

  2. int_1: holds an integral constant of type int whose value is 1

  3. uint_1: holds an integral constant of type unsigned int whose value is 1

To verify that they are distinct types, write a set of overloaded functions taking each of these types, create objects of these types, and call the corresponding overloaded function.

Exercise 3

Write a function template that takes an argument of a type that is a specialization of integral_constant and displays the value of the argument's member value, the type named by the argument type's nested typedef value_type, and the type named by the argument type's nested typedef type. Call the function template with the typedefs TRue_type and false_type from the TR1 library and with the typedefs written in the preceding example.

Exercise 4

Write a function template that shows the result of applying each of the primary type predicates to the type of its template argument. Use this function template to verify the assertion in Section 11.3 that categories defined by the primary type predicates are complete and exclusive.

Exercise 5

Write a function template that checks whether each of the composite type predicates gives the correct result for the type of its template argument. Use this function template to check the results of the composite type predicates for several different types.

Exercise 6

Write a class template that takes one type argument and holds a typedef named type that names the same type as the type argument but with no const qualifier and with a volatile qualifier. Use the class template in a program that verifies that it works correctly by testing for each of those qualifiers.

Exercise 7

Write a function template to copy a range of values designated by a pair of iterators to a range designated by an output iterator using memcpy.[8] Write a function template to copy a range of values designated by a pair of iterators to a range designated by an output iterator, copying each element individually. Write a function template to copy a range of values designated by a pair of iterators to a range designated by an output iterator, using the first function if the type being copied has a trivial copy assignment operator and using the second function if it does not. Write a class that has a non-trivial copy assignment operator. Write a program that creates two arrays of objects of that type and two arrays of int values, copies the values from one of the arrays of objects to the other, and copies the values from one of the arrays of int values to the other, using the third copy function that you wrote. Verify that the copy operation does not use memcpy for the array of objects and that it uses memcpy for the array of int values.

[8] In order to use memcpy, the data being copied must be contiguous. No iterator type guarantees contiguous data, so you must know the source of your data if you're going to do this.

Exercise 8

Write a function template that returns the transpose of a two-dimensional array with arbitrary extents.[9]

[9] The transpose of an array arr0 of type Ty[M][N] is an array arr1 of type Ty[N][M] such that arr1[j][i] == arr0[i][j] for all values of i in the half-open range [0, M) and all values of j in the half-open range [0, N).

Exercise 9

Write a program that shows the alignment requirement given by the class template alignment_of for various integral, floating-point, and pointer types. If your compiler has a switch for controlling alignmentmost docompile the program with different alignment settings to see how the results are affected by the switch.


Part V: Numerics

    Chapter 12. Numeric Functions

    Chapter 13. Random Number Generators


Chapter 12. Numeric Functions

Fast is good. Accurate is better.

ATTRIBUTED TO WYATT EARP

The C standard was revised in 1999 to improve support for fast, robust floating-point computations.[1] This revision came a year after the C++ standard was approved, so these changes are not part of the C++ standard.[2] The C99 changes to the C library are, however, included in the TR1 library, along with two dozen new math functions that are now being considered for addition to C.

[1] The revision made changes in other areas, as well. See Chapter 22.

[2] The C++ standard was revised in 2003, but the Standards Committee only made changes needed to fix defects.

The C99 changes add three headers to the standard C library: <fenv.h>, which describes an interface for examining and modifying a program's floating-point environment; <tgmath.h>, which defines several type-generic macros that provide Fortran-like promotion rules for arguments to functions taking floating-point arguments and complex arguments; and <complex.h>, which provides support for complex arithmetic. The C99 changes also make small changes to the rules for handling errors in math functions and add several new functions that are declared in <math.h>.

In the TR1 library, the support for accessing the floating-point environment is provided through <float.h>, <cfloat>, <fenv.h>, and <cfenv>; see Section 12.3. The changes to the rules for error handling require some additions to <math.h> and <cmath>; see Section 12.5. The Fortran-like promotion rules are provided through ordinary function overloading; see Section 12.6. The new mathematical functions from C99 are declared in <math.h> and <cmath>; see Section 12.7. The C++ mathematical special functions are also declared in <math.h> and <cmath>; see Section 12.8. The functions that take complex arguments are declared in <complex.h> and <ccomplex>; see Section 12.9.


Section 12.1. About the Examples

12.1. About the Examples

Most of the examples in this chapter use a header file named "mathutil.h". This header file defines a function, show_exceptions, that displays the floating-point exceptions that are currently raised. For details, see Appendix B.2.

Compiler optimizations often hide exceptions. For example, the expression 0.0/0.0 should raise the "invalid" exception. However, compilers often evaluate an expression like that at compile time and simply plug in a NaN (not a number) value instead of doing the division at runtime. The result is that no exception is raised. This can be very confusing.

C99 has a #pragma directive to tell the compiler that you're going to be testing the floating-point status flag and to report everything that happens. I haven't used it in these examples, because it's not required by the C++ standard.[3] If your compiler supports it, though, you should add

[3] TR1 is entirely library extensions and doesn't add anything to the language itself.

#include <fenv.h>
#pragma STDC  FENV_ACCESS ON

to the beginning of all your test programs.

If your compiler doesn't support this pragma, turn off optimizations. You may also have to play around with the way you write expressions. For example, the function

double divide(double x, double y)
  {
  return x / y;
  }

doesn't raise "inexact" when called with divide(2.0, 3.0). Rewriting it as

double divide(double x, double y)
  {
  double res = x / y;
  return res ;
  }

fixes this problem.


Section 12.2. Representing Floating-Point Values

12.2. Representing Floating-Point Values

Floating-point math is tricky, and most programmers don't understand it well enough to use it correctly. Since I'm in that group, I'm not going to write about how to get accurate results from complex computations.[4]

[4] People get PhDs in how to do floating-point math accurately. A little closer to home, P.J. Plauger and Chris Walker, both also at Dinkumware, have burned thousands of hours of computer time refining the Dinkumware implementation of the TR1 Math Special Functions (Section 12.8), producing results that are far more accurate than any other implementation of these functions that we know of.

12.2.1. The Floating-Point Model

The C99 standard uses an abstract model to describe the representation of floating-point values. A floating-point value x is represented as:

where β and p are characteristics of the floating-point representation (float, double, or long double).

  • β is the base of the floating-point representation. It must be an integer with a value of 2 or more. Most floating-point representations today use a base of 2, although base 10 is gaining in popularity.

  • p is the precision of the floating-point value, that is, the number of digits in base β in a value's significand.

  • Each digit di is greater than or equal to 0 and less than β.

The values of e and the various d is are determined by the particular value being represented.

  • The value e is the exponent that the base should be raised to.

  • The values di are the digits in the value's significand.

For example, .602 x 1024 represents a value in base 10 (β = 10) having three significant digits (p = 3). Its digits are 6, 0, and 2 (d1 = 6, d2 = 0, and d3 = 2); its exponent is 24 (e = 24); and its significand is .602.

A floating-point value is normalized if its value is 0 or if d 1 > 0.[5] So .602 x 1024 is normalized, and .0602 x 1025, even though it represents the same value, is not. A floating-point value is denormalized if its value is not 0 and d1 = 0.

[5] Thus, in a normalized representation, the value of the significand of a nonzero number is always greater than or equal to 1/β and less than 1.

12.2.2. Properties of Floating-Point Types

C and C++ provide three floating-point typesfloat, double, and long doubledistinguished by the range of values that the type can represent. Sometimes it's important to know the limits on these ranges. You can find these limits in two ways: In C and C++, you can use the macros defined in the header <float.h>[6] (as well as <cfloat> in C++); in C++, you can also use the numeric_limits template defined in the header <limits>. Table 12.1 lists the macros and numeric_limits members that describe the fundamental properties of the type double.[7] The resulting values are all compile-time constants.

[6] The full contents of this header are presented in Appendix A, in Section A.4.

[7] Similar macros, with names that begin with FLT and LDBL instead of DBL, describe the properties of the types float and long double, respectively. The members of the template specializations numeric_limits<float> and numeric_limits<long double> describe float and long double.

Table 12.1. Fundamental Floating-Point Properties

<float.h>

numeric_limits <double>

Definition

FLT_RADIX

radix

β, the base of the floating-point representation

DBL_MANT_DIG

digits

p, the number of digits in the significand

DBL_MIN_EXP

min_exponent

emin, the minimum value of e such that βe-1 is normalized and nonzero

DBL_MAX_EXP

max_exponent

emax, the maximum value of e such that βe-1 is representable

The four values in Table 12.1 completely describe the numbers that can be represented as normalized values. However, since most uses of floating-point math involve decimal values, it's convenient to have decimal approximations[8] of the precision and minimum and maximum exponents. The code for these properties is in Table 12.2. These values, too, are all compile-time constants.

[8] Which are, of course, exact when the base of the representation is 10.

Table 12.2. Decimal-valued Floating-Point Properties

<float.h>

numeric_limits <double>

Definition

DBL_DIG

digits10

The number of decimal digits representable in the significand: p log10 β if β is a power of 10; otherwise, [image] (p - 1) log10β

DBL_MIN_10_EXP

min_exponent10

The minimum value of y such that 10y is normalized and nonzero: log10βemin-1

DBL_MAX_10_EXP

max_exponent10

The maximum value of y such that 10y is representable: log10((1 - β-p)βe max)

Three other values are important when you need to understand the results of a floating-point computation. Access to the minimum and maximum floating-point values and another way of handling precision are described in Table 12.3. The values that you get from the C macros are compile-time constants; the values from the numeric_limits template are not.

Table 12.3. Other Floating-Point Properties

<float.h>

numeric_limits <double>

Definition

DBL_MIN

min()

βe min -1, the minimum positive normalized value

DBL_MAX

max()

(1 β-p)βe max, the maximum representable finite value

DBL_EPSILON

epsilon()

β1 - p, one less than the least representable value greater than 1

12.2.3. Floating-Point Types

The C and C++ standards give mimimum or maximum values for several of the properties described in the previous section.[9] The requirements for float result in a smaller range and less precision than the requirements for double; the requirements for long double are the same as the requirements for double, but some implementations provide a larger range and more precision. These requirements are listed in Table 12.4.

[9] Since floating-point values are written in base 10, the requirements are given for the base 10 versions of the various properties.

Table 12.4. Required Values for Floating-Point Properties

Property numeric_limits

float

double

radix

>= 2

>= 2

digits10

>= 6

>= 10

min_exponent10

>= -37

>= -37

max_exponent10

>= 37

>= 37

min()

>= 1e-37

>= 1e-37

max()

>= 1e37

>= 1e37

epsilon()

<= 1e-5

<= 1e-9

For an implementation that conforms to the IEC 60559 Standard [Int89], the requirements given in Table 12.5 [10] apply. Again, the requirements for long double are the same as for double.

[10] The C99 standard gives more details.

Table 12.5. Floating-Point Properties for IEC 60559

Property numeric_limits

float

double

radix

2

2

digits

24

53

min_exponent

-125

-1021

max_exponent

128

1024

digits10

6

15

min_exponent10

-37

-307

max_exponent10

38

308

min()

1.17549435e-38f

2.2250738585072014e-308

max()

3.40282347e38f

1.7976931348623157e308

epsilon()

1.19209290e-7f

2.2204460492503131e-16


Section 12.3. Managing the Floating-Point Environment

12.3. Managing the Floating-Point Environment

In the TR1 library the header <fenv.h> provides definitions for two types and several macros and declarations for eleven functions. The types and function names are in the global namespace. The header <cfenv> provides the same definitions and declarations, with the types and function names in the nested namespace std::tr1.

These types and functions provide functionality that matches IEC 60559 but can be applied to similar floating-point implementations. Keep in mind that some of the operations are optional; the functions return an error code if they can't do what was requested.

12.3.1. The Header <fenv.h>

The header <fenv.h> defines the following types and macros and declares the following functions. We look at all of them in more detail in the sections that follow.

  // FLOATING-POINT ENVIRONMENT
typedef o-type fenv_t ;

#define FE_DFL_ENV <const * fenv_t rvalue>

int fegetenv (fenv_t * penv);
int fesetenv (const fenv_t * penv);

  // ROUNDING
#define FE_DOWNWARD <integer constant expression>
#define FE_TONEAREST <integer constant expression>
#define FE_TOWARDZERO <integer constant expression>
#define FE_UPWARD <integer constant expression>

int fegetround ();
int fesetround (int mode);

  // EXCEPTIONS
#define FE_INEXACT <integer constant expression>
#define FE_INVALID <integer constant expression>
#define FE_OVERFLOW <integer constant expression>
#define FE_UNDERFLOW <integer constant expression>
#define FE_DIVBYZERO <integer constant expression>
#define FE_ALL_EXCEPT <integer constant expression>

int feclearexcept (int except);
int feraiseexcept (int except);
int fetestexcept (int except);

typedef i-type fexcept_t;
int fegetexceptflag (fexcept_t * pflag, int except);
int fesetexceptflag (const fexcept_t * pflag, int except);

int feholdexcept (fenv_t * penv);
int feupdateenv (const fenv_t * penv);

The floating-point environment consists of the floating-point control mode and the floating-point status flag.

  • The floating-point control mode is an internal variable that controls how floating-point computations are done. You can use the function fegetround to get the rounding rule that is currently being used, and you can use the function fesetround to set the rounding rule. See Section 12.3.3. Each implementation can add functions that manage other aspects of floating-point computations.[11]

    [11] In particular, many implementations allow installing a trap handler, which will be called when a particular floating-point exception occurs.

  • The floating-point status flag holds a value that indicates which exceptions have been raised since the last time the flag was cleared. A floating-point exception occurs when a floating-point computation goes astray in various ways.[12] The TR1 library[13] distinguishes five kinds of floating-point exceptions: division by zero, inexact, invalid, overflow, and underflow. See Section 12.3.4.

    [12] Don't confuse floating-point exceptions with C++ exceptions; they're completely unrelated.

    [13] And C99 and IEC 60559.

In general, when you write a function that does floating-point math, you can make the following assumptions about the floating-point control mode.

  • When your function is called, the floating-point control mode will be in its default state.

  • Any function that your code calls will not change the floating-point control mode.

  • Any function that your code calls requires that the floating-point control mode be in its default state.

This also means that code that calls your function and code that your function calls can make the same assumptions. To obey these conventions, you can change the floating-point control mode within your function, [14] but when your function calls other functions and when it returns, the floating-point control mode must first be restored to its default state.

[14] Or, of course, within a related set of functions that are within your control.

You can also make the following assumptions about the floating-point status flags.

  • Any function that your code calls will not clear the floating-point status flags.

  • Any function that your code calls will not depend on the state of the floating-point status flags.

The general rule here is that the floating-point status flags are "sticky"; once set, they stay set until the program takes explicit action to clear them. This means that you can do a lengthy floating-point computation without having to check the status flags until the end. If anything went wrong, the flags will have that information. Just as with the floating-point control mode, this doesn't mean that your function can't clear the status flags; it means that if it does clear them, it has to restore the ones that it cleared before returning.

12.3.2. The Floating-Point Environment

typedef o-type fenv_t ;

The type is an object type o-type that can represent the settings of the floating-point environment (Section 12.3.1).

Keep in mind that this is an opaque type; each implementation can use a different representation. The only valid way of setting and examining values is through the various following interface functions.

#define FE_DFL_ENV <const * fenv_t rvalue>

The macro expands to a pointer to an object that describes the settings for the floating-point environment at program startup.

int fegetenv (fenv_t * penv);

The function attempts to store the current floating-point environment settings at *penv. It returns 0 only if the store succeeds.

int fesetenv (const fenv_t * penv);

The function attempts to restore the floating-point environment settings to the values stored in *penv. It returns 0 only if the settings are successfully restored. The argument penv must be the value of the macro FE_DFL_ENV or must point to an object of type fenv_t whose contents were stored by a previous call to fegetenv or feholdexcept.

The functions fegetenv and fesetenv work together to save and restore the floating-point environment. For example, to enforce the conventions set out in Section 12.3.2, you could write the following code.

Example 12.1. The Floating-Point Environment (math/fpenv.cpp)

#include <fenv.h>
#include <iostream>
#include "mathutil.h"
using std::cout;

class save_fp_env
  { // class to save and restore floating-point environment
public :
  save_fp_env() { fegetenv (&env); }
  ~save_fp_env() { fesetenv (&env); }
private :
  fenv_t env;
  };

double divide(double x, double y)
  { // simple floating-point computation
  save_fp_env env;
  double res = x / y;
  show_exceptions ("in function 'divide'");
  return res;
  }

int main()
  { // demonstrate saving and restoring floating-point environment
  show_exceptions(
    "in function 'main' before call to 'divide'");
  divide (2.0, 3.0);
  show_exceptions (
    "in function 'main' after call to 'divide'");
  return 0;
  }

12.3.3. Rounding

The rounding mode, which can be represented as an integral value, determines how floating-point values convert to integers. The rounding modes are

Downward: to the nearest more negative integer

To nearest: to the integer with the closest value or toward the nearest even integer if the two nearest integers are equally near

Toward zero: to the nearest integer closer to 0 (also called truncation)

Upward: to the nearest more positive integer

An implementation may define additional rounding modes.

#define FE_DOWNWARD < integer constant expression >
#define FE_TONEAREST < integer constant expression >
#define FE_TOWARDZERO < integer constant expression >
#define FE_UPWARD < integer constant expression >

The macros each expand to an integer value accepted as an argument to fesetround and returned by fegetround to indicate a rounding mode of downward, to nearest, toward zero, and upward, respectively. The macros are not defined if the functions defined in this header cannot control the rounding mode.

int fegetround ();

The function returns the current rounding mode or a negative value if the current rounding mode cannot be determined.

int fesetround (int mode);

The function sets the current rounding mode to mode. An invalid value of mode leaves the rounding mode unchanged. The function returns 0 only if the rounding mode is successfully set to mode.

12.3.4. Exceptions

A function can change the floating-point status (Section 12.3.1) by reporting one of several floating-point exceptions:

Inexact: when a finite floating-point result cannot be exactly represented, as in 2.0 / 3.0

Invalid: when a floating-point operation involves an invalid combination of operators and operands, as in 0.0 / 0.0

Overflow: when the magnitude of a finite floating-point result is too large to represent, as in DBL_MAX / DBL_MIN

Underflow: when the magnitude of a nonzero floating-point result is too small to represent, as in DBL_MIN / DBL_MAX

Divide-by-zero: when a floating-point divide has a finite dividend and a zero divisor, as in 1.0 / 0.0

An implementation may define additional floating-point exceptions, which should be identified with macros whose names begin with FE_ followed by an uppercase letter.

Reporting an exception sets a corresponding indicator in the floating-point status (Section 12.3.1). Reporting can also raise a floating-point exception, which can result in a hardware trap or the raising of a C signal or both.

#define FE_INEXACT < integer constant expression >
#define FE_INVALID < integer constant expression >
#define FE_OVERFLOW < integer constant expression >
#define FE_UNDERFLOW < integer constant expression >
#define FE_DIVBYZERO < integer constant expression >

The macros expand to integer values that can be ORed together to produce distinct values. The macros designate floating-point exceptions of type inexact, invalid, overflow, underflow, and divide-by-zero, respectively. They can be passed as arguments to several of the functions declared in the header <fenv.h> to designate which exceptions the function should be applied to. Each macro is defined only if the functions defined in this header can control floating-point exceptions of that type.

#define FE_ALL_EXCEPT < integer constant expression >

The macro expands to an integer value that is the bitwise OR of all the floating-point exception macros that the implementation defines. The macro is not defined if the functions defined in this header cannot control floating-point exceptions.

int feclearexcept (int except);

The function attempts to clear the exceptions selected by except in the floating-point status (Section 12.3.1). It returns 0 only if except is 0 or all the exceptions selected by except are successfully cleared.

int feraiseexcept (int except);

The function attempts to raise (Section 12.3.4) the floating-point exceptions specified by except. Whether it raises an "inexact" floating-point exception after an "overflow" floating-point exception or an "underflow" floating-point exception is implementation-defined. The function returns 0 only if except is 0 or all the exceptions selected by except are successfully raised.

int fetestexcept (int except);

The function returns a nonzero value only if one or more of the exceptions selected by except is set in the floating-point status (Section 12.3.1).

The functions feclearexcept, feraiseexcept, and fetestexcept treat exceptions as an abstraction that is represented by a set of flags that can each be set or cleared. Thus, feclearexcept clears the flags given by its argument; fetestexcept tests the status of the flags given by its argument; and feraiseexcept sets the flags given by its argument and takes any additional action supported by the floating-point implementation when an exception is raised (Section 12.3.4).

Example 12.2. Manipulating Exception Flags (math/flags.cpp)

#include <fenv.h>
#include <iostream>
#include "mathutil.h"
using std::cout;

int main()
  { // demonstrate feraiseexcept, feclearexcept, and fetestexcept
  show_exceptions ("at start of 'main'");
  feraiseexcept(FE_INEXACT);
  show_exceptions ("after call to 'feraiseexcept'");
  feclearexcept(FE_INEXACT);
  show_exceptions ("after call to 'feclearexcept'");
  return 0;
  }

typedef o - type fexcept_t ;

The type is an object type o-type that can represent the floating-point status (Section 12.3.1), including any additional implementation-specific information.

int fegetexceptflag (fexcept_t * pflag, int except);

The function attempts to store in *pflag a representation of the exceptions selected by except from the floating-point status (Section 12.3.1). It returns 0 only if except is 0 or all the exceptions selected by except are successfully stored.

int fesetexceptflag (const fexcept_t * pflag, int except);

The function attempts to restore the exceptions selected by except to the status stored in *pflag. It returns 0 only if except is 0 or all the exceptions selected by except are successfully restored. The value stored in *pflag must be determined by an earlier call to fegetexceptflag.

The functions fegetexceptflag and fesetexceptflag support a more detailed, implementation-specific notion of a floating-point exception than that supported by feclearexcept, feraiseexcept, and fetestexcept. Because the type fexcept_t can hold implementation-specific information, you can't use fesetexceptflag to raise arbitrary exceptions; you can use it only to restore exceptions whose status was saved previously by a call to fegetexceptflag.

Example 12.3. Manipulating Full Exception Status (math/status.cpp)

#include <fenv.h>
#include <iostream>
#include "mathutil.h"
using std::cout;

double divide(double x, double y)
  { // simple floating-point computation
  double res = x / y;
  show_exceptions ("in call to 'divide'");
  return res;
  }

int main()
  { // demonstrate fegetexceptflag and fesetexceptflag
  fexcept_t except ;
  fegetexceptflag (&except, FE_INEXACT | FE_DIVBYZERO);
  show_exceptions ("at start of 'main'");
  divide (2.0, 3.0);
  show_exceptions ("after call to 'divide'");
  divide (2.0, 0.0);
  show_exceptions ("after second call to 'divide'");
  fesetexceptflag (&except, FE_INEXACT);
  show_exceptions ("after call to 'fesetexceptflag'");
  return 0;
  }

int feholdexcept (fenv_t * penv);

The function attempts to store the current floating-point environment settings at *penv. It then clears any exceptions in the floating-point status flags (Section 12.3.1) and attempts to establish settings that will not raise any floating-point exceptions. It returns 0 only if it succeeds.

int feupdateenv (const fenv_t * penv);

The function first stores a copy of the current floating-point status flag, then attempts to restore the floating-point environment settings to the values stored in *penv, and then raises the saved exceptions. It returns 0 only if the settings are successfully restored.

You can use the functions feholdexcept and feupdateenv to defer the raising of exceptions until spurious ones are cleared.

Example 12.4. Deferring Exceptions (math/defer.cpp)

#include <fenv.h>
#include <iostream>
#include "mathutil.h"
using std::cout;

class hold_exceptions
  { // class to defer raising of exceptions
public:
  hold_exceptions() { feholdexcept (&env); }
  ~hold_exceptions()
    { // ignore inexact, raise all others
    feclearexcept (FE_INEXACT);
    feupdateenv (&env);
    }
private:
  fenv_t env;
  };

double divide(double x, double y)
  { // simple floating-point computation
  hold_exceptions holder;
  double res = x / y;
  show_exceptions ("in call to 'divide'");
  return res;
  }

int main()
  { // demonstrate feholdexcept and feupdateenv

  show_exceptions ("at start of 'main'");
  divide (2.0, 3.0);
  show_exceptions ("after call to 'divide'");
  divide (2.0, 0.0);
  show_exceptions ("after second call to 'divide'");
  return 0;
  }


Section 12.4. Infinities, Denormals, NaNs, and Comparisons

12.4. Infinities, Denormals, NaNs, and Comparisons

The IEC 60559 standard formalizes several special kinds of floating-point values that can arise when something goes wrong in a floating-point computation. For example, dividing a nonzero value by zero is an error. However, code that checks the divisor of every division operation to detect division by zero will be bulky and slow. So the IEC 60559 standard provides the values positive infinity and negative infinity; division by zero produces one of these two values, and because of the rules for mathematical operations whose operands are infinities, such values persist. As a result, you don't need to check for division by zero; you can wait until the end of a computation and check whether the result is infinity.

At the other extreme, dividing a small positive value by a large positive value can produce a result that is too small to represent in normalized (Section 12.2.1) form. Usually, such a value becomes 0. However, IEC 60559 allows, but does not require, implementations to represent such values in denormalized (Section 12.2.1) form. The leading zeros in the significand of a denormalized value mean that the value has less precision than the number of bits in the significand implies. The significand of the smallest possible denormalized value has all its digits equal to 0 except for the last, which is 1. The next smaller value is 0.

An operation that has no meaningful result, such as dividing 0 by 0, produces a value known as not-a-number, or NaN . NaNs, too, persist in a computation; operations, other than comparisons, that involve NaN values produce NaN results. IEC 60559 requires implementations to support at least one NaN value and allows more than one.[15]

[15] In fact, it permits two flavors of NaN, as well: quiet NaNs and signaling NaNs. Any operation on a signaling NaN produces a quiet NaN, so you can do very little with signaling NaNs.

The usual comparison operators, when applied to any NaN value, evaluate to false. Technically, NaN values are unordered. The TR1 library provides functions to determine whether a number is a NaN and whether a particular comparison is unordered, so you can check whether a comparison is telling you what you think it is.

If the value of std::numeric_limits<double>::is_iec559 is TRue, the implementation supports the IEC 60559 standard. If std::numeric_limits<double>::has_denorm equals std::denorm_present, the implementation supports denormalized values. If the value of std::numeric_limits< double>::has_quiet_NaN is TRue, the implementation supports NaN values, and you can get a NaN value by calling std::numeric_limits<double>:: quiet_NaN().


Section 12.5. Domain and Range Errors

12.5. Domain and Range Errors

A domain error occurs when a function is not defined for its input argument value or values. A range error occurs when the return value of a function is defined but cannot be represented. The headers <math.h> and <cmath> define several macros for error handling.

#define MATH_ERRNO 1
#define MATH_ERREXCEPT 2
#define math_errhandling < int rvalue >

The value of the macro math_errhandling doesn't change during program execution. As its name suggests, it gives you information about how math errors are handled in library functions.

  • If (math_errhandling & MATH_ERRNO) != 0, a math function stores a nonzero value in errno and returns a particular value that characterizes the error.

  • If (math_errhandling & MATH_ERREXCEPT) != 0, a math function raises an invalid floating-point exception (Section 12.3.4). In this case, the macros FE_INVALID, FE_OVERFLOW and FE_DIVBYZERO are all defined.

#define HUGE_VAL <double rvalue>
#define HUGE_VALF <float rvalue>
#define HUGE_VALL <long double rvalue>

The macros HUGE_VAL, HUGE_VALF, and HUGE_VALL yield values of type double, float, and long double, respectively, returned by some functions on a range error. The values can be representations of infinity.


Section 12.6. New Overload Rules

12.6. New Overload Rules

The C99 header <tgmath.h> provides type-generic macros that support Fortran-like argument promotion rules for the functions declared in the header <math.h> that take floating-point arguments and for the functions declared in the header <complex.h> that take complex arguments. In the TR1 library these argument promotion rules are supported through overloading.

  • If the function takes an argument of a floating-point type, an integer argument is converted by a typecast to double before determining the function to call.

  • For a function with two or more arguments, the arguments are each converted according to the previous rule, then converted by a typecast to the type of the sum of all the arguments before determining the function to call.

In practice, this means that determining which version of a function to call requires two steps. First, if any integer arguments are passed where the function expects a floating-point value, promote those integer arguments to type double; second, from the types of the arguments passed to the function, pick the one that's earliest on this list:

  • complex<long double>

  • complex<double>

  • complex<float>

  • long double

  • double

  • float

The overload to choose is the one that takes that argument type.

Example 12.5. New Overload Rules (math/overload.cpp)

#include <math.h>

void test()
  {
  int i_val = 2;
  float f_val = 2.0F;
  double d_val = 2.0;
  long double ld_val = 2.0 L;
  atan2(i_val, d_val);       // calls atan2(double, double)
  atan2(i_val, f_val);       // calls atan2(double, double)
  atan2(f_val, f_val);       // calls atan2(float, float)
  atan2(f_val, ld_val);      // calls atan2(long double, long double)
  }


Section 12.7. Basic Math Functions

12.7. Basic Math Functions

The partial synopsis of the header <math.h>[16] that follows gives the declarations for the various basic mathematical functions that take arguments of type double. Each of these functions also has a version that takes arguments of type float and returns a value of type float, indicated by the letter f at the end of the function's name, and a version that takes arguments of type long double and returns a value of type long double, indicated by the letter l at the end of the function's name. In addition, each function has overloaded versions, taking arguments of type float and long double. These overloads have the same name as the double version. In addition, overloads are available as needed to satisfy the new overload rules (Section 12.6).

[16] The complete synopsis is in Appendix A.5.

The header <cmath> also provides all these functions, with their names nested in the namespace std::tr1.

12.7.1. Header <math.h> Synopsis

  // CLASSIFICATION FUNCTIONS
template<class Ty> int fpclassify(Ty x);
template<class Ty> bool isfinite(Ty x);
template<class Ty> bool isinf(Ty x);
template<class Ty> bool isnan(Ty x);
template<class Ty> bool isnormal(Ty x);
template<class Ty> bool signbit(Ty x);

  // COMPARISON FUNCTIONS
template<class Ty> bool isgreater(Ty x, Ty y);
template<class Ty> bool isgreaterequal(Ty x, Ty y);
template<class Ty> bool isless(Ty x, Ty y);
template<class Ty> bool islessequal(Ty x, Ty y);
template<class Ty> bool islessgreater(Ty x, Ty y);
template<class Ty> bool isunordered(Ty x, Ty y);

  // ABSOLUTE VALUES
double abs(double x);
double fabs(double x);

  // MINIMUM AND MAXIMUM
double fdim(double x, double y);
double fmax(double x, double y);
double fmin(double x, double y);

  // ROUNDING
double ceil(double x);
double floor(double x);
double nearbyint(double x);
double rint(double x);
double lrint(double x);
long long llrint(double x);
double round(double x);
long lround(double x);
long long llround(double x);
double trunc(double x);

  // REMAINDERS
double fmod(double x, double y);
double remainder(double x, double y);
double remquo(double x, double y, int *pquo);

  // TRIGONOMETRIC FUNCTIONS
double acos(double x);
double asin(double x);
double atan(double x);
double atan2(double y, double x);
double cos(double x);
double sin(double x);
double tan(double x);

  // HYPERBOLIC FUNCTIONS
double acosh(double x);
double asinh(double x);
double atanh(double x);
double cosh(double x);
double sinh(double x);
double tanh(double x);

  // EXPONENTIAL FUNCTIONS
double exp(double x);
double exp2(double x);
double expm1(double x);

  // LOGARITHMS
double logb(double  x);
int ilogb(double x);
double log(double x);
double log10(double x);
double log1p(double x);
double log2(double x);

  // POWERS AND ROOTS
double pow(double x, double   y);
double cbrt(double x);
double sqrt(double x);
double hypot(double x, double y);

  // SCALING
double frexp(double x, int  *pexp);
double ldexp(double x, int  ex);
double modf(double x, double  *pint);
double scalbn(double x, int ex);
double scalbln(double x, long ex);

  // VALUE MANIPULATORS
double copysign(double x, double y);
double nan(const char *str);
double nextafter(double x, double y);
double nexttoward(double x, long double y);

  // FLOATING MULTIPLY-ADD
double fma(double x, double y, double z);

  // MACROS
#define FP_FAST_FMA <integer constant expression>
#define FP_FAST_FMAF <integer constant expression>
#define   FP_FAST_FMAL <integer constant expression>
#define FP_ILOGB0 <integer constant expression>
#define FP_ILOGBNAN <integer constant expression>

#define FP_INFINITE <integer constant expression>
#define FP_NAN <integer constant expression>
#define FP_NORMAL <integer constant expression>
#define FP_SUBNORMAL <integer constant expression>
#define FP_ZERO <integer constant expression>

#define INFINITY <float rvalue>
#define NAN <float rvalue>

12.7.2. Classification Functions

These function templates provide information about their argument without raising any floating-point exceptions. C99 provides macros with the same names that do the same things.

template<class Ty> int fpclassify(Ty x);
#define FP_INFINITE <integer constant expression>
#define FP_NAN <integer constant expression>
#define FP_NORMAL <integer constant expression>
#define FP_SUBNORMAL <integer constant expression>
#define FP_ZERO <integer constant expression>

The function template returns one of the following or possibly some other implementation-defined value:

  • FP_INFINITE if x is negative or positive infinity

  • FP_NAN if x is NaN

  • FP_NORMAL if x is finite and normalized

  • FP_SUBNORMAL if x is finite and denormalized

  • FP_ZERO if x is negative or positive 0

template < class Ty > bool isfinite (Ty x);

The function template returns TRue only if x is finite.

template<class Ty> bool isinf(Ty x);

The function template returns true only if x is positive or negative infinity.

template<class Ty> bool isnan(Ty x);

The function template returns true only if x is NaN.

template<class Ty> bool isnormal(Ty x);

The function template returns true only if x is finite and normalized.

template<class Ty> bool signbit(Ty x);

The function template returns TRue only if the (negative) sign bit of x is set. The functions never raise an "invalid" floating-point exception.

12.7.3. Comparison Functions

template<class Ty> bool isgreater(Ty x, Ty y);

The function template returns true only if x > y and neither x nor y is NaN. Unlike the > operator, the functions never raise an "invalid" floating-point exception.

template<class Ty> bool isgreaterequal(Ty x, Ty y);

The function template returns true only if x >= y and neither x nor y is NaN. Unlike the >= operator, the functions never raise an "invalid" floating-point exception.

template<class Ty> bool isless(Ty x, Ty y);

The function template returns true only if x < y and neither x nor y is NaN. Unlike the < operator, the functions never raise an "invalid" floating-point exception.

template<class Ty> bool islessequal(Ty x, Ty y);

The function template returns true only if x <= y and neither x nor y is NaN. Unlike the <= operators, the functions never raise an "invalid" floating-point exception.

template<class Ty> bool islessgreater(Ty x, Ty y);

The function template returns true only if x < y || x > y and neither x nor y is NaN. Unlike the != operator, the functions never raise an "invalid" floating-point exception.

template<class Ty> bool isunordered(Ty x, Ty y);

The function template returns true only if at least one of the two arguments is NaN. The functions never raise an "invalid" floating-point exception.

12.7.4. Absolute Values

double abs(double x);
float abs(float x);
long double abs(long double x);

double fabs(double x);
float fabs(float x);
long double fabs(long double x);
float fabsf(float x);
long double fabsl(long double x);

The functions return the magnitude of x, |x|.

Note that the headers <stdlib.h> and <cstdlib> also define overloaded versions of abs.

12.7.5. Minimum and Maximum

double fdim(double x, double y);
float fdim(float x, float y);
long double fdim(long double x, long double y);
float fdimf(float x, float y);
long double fdiml(long double x, long double y);

The functions return the larger of x - y and 0.

double fmax(double x, double y);
float fmax(float x, float y);
long double fmax(long double x, long double y);
float fmaxf(float x, float y);
long double fmaxl(long double x, long double y);

The functions return the greater of x and y, TReating all values of NaN as a single value less than any non-NaN value.

double fmin(double x, double y);
float fmin(float x, float y);
long double fmin(long double x, long double y);
float fminf(float x, float y);
long double fminl(long double x, long double y);

The functions return the lesser of x and y, treating all values of NaN as a single value greater than any non-NaN value.

12.7.6. Rounding

double ceil(double x);
float ceil(float x);
long double ceil(long double x);
float ceilf(float x);
long double ceill(long double x);

The functions return the smallest integer value not less than x.

double floor(double x);
float floor(float x);
long double floor(long double x);
float floorf(float x);
long double floorl(long double x);

The functions return the largest integer value not greater than x.

double nearbyint(double x);
float nearbyint(float x);
long double nearbyint(long double x);
float nearbyintf(float x);
long double nearbyintl(long double x);

The functions return x rounded to the nearest integer, consistent with the current rounding mode but without raising an "inexact" floating-point exception.

double rint(double x);
float rint(float x);
long double rint(long double x);
float rintf(float x);
long double rintl(long double x);

The functions return x rounded to the nearest integer, consistent with the current rounding mode. They may raise an "inexact" floating-point exception if the return value does not equal x.

double lrint(double x);
float lrint(float x);
long double lrint(long double x);
float lrintf(float x);
long double lrintl(long double x);

The functions return the nearest long integer to x, consistent with the current rounding mode.

long long llrint(double x);
long long llrint(float x);
long long llrint(long double x);
long long llrintf(float x);
long long llrintl(long double x);

The functions return the nearest long long integer to x, consistent with the current rounding mode.

double round(double x);
float round(float x);
long double round(long double x);
float roundf(float x);
long double roundl(long double x);

The functions return x rounded to the nearest integer n or to the value with larger magnitude if |n - x| == 1/2.

long lround(double x);
long lround(float x);
long lround(long double x);
long lroundf(float x);
long lround(lolng double x);

The functions return the nearest long integer to x, rounding halfway values away from 0, regardless of the current rounding mode.

long long llround(double x);
long long llround(float x);
long long llround(long double x);
long long llroundf(float x);
long long llroundl(long double x);

The functions return the nearest long long integer to x, rounding halfway values away from 0, regardless of the current rounding mode.

double trunc(double x);
float trunc(float x);
long double trunc(long double x);
float truncf(float x);
long double truncl(long double x);

The functions return x rounded to the nearest integer not larger in magnitude than x (toward 0).

12.7.7. Remainders

double fmod(double x, double y);
float fmod(float x, float y);
long double fmod(long double x, long double y);
float fmodf(float x, float y);
long double fmodl(long double x, long double y);

The functions return the remainder of x/y, defined as follows.

  • If y is 0, the functions either report a domain error or simply return 0.

  • Otherwise, the functions determine the signed integer value i such that the returned value x - i*y has the same sign as x and magnitude less than |y|.

double remainder(double x, double y);
float remainder(float x, float y);
long double remainder(long double x, long double y);
float remainderf(float x, float y);
long double remainderl(long double x, long double y);

The functions effectively return remquo(x, y, &temp), where temp is a temporary object of type int local to the function.

double remquo(double x, double y, int *pquo);
float remquo(float x, float y, int *pquo);
long double remquo(long double x, long double y, int *pquo);
float remquof(float x, float y, int *pquo);
long double remquol(long double x, long double y, int *pquo);

The functions compute the remainder rem = x - n*y, where n = x/y rounded to the nearest integer or to the nearest even integer if |n - x/y| == 1/2. If rem is 0, it has the same sign as x. A domain error occurs if y is 0.

The function stores in *pquo at least three of the low-order bits of |x/y|, negated if x/y < 0. It returns rem.

12.7.8. Trigonometric Functions

double acos(double x);
float acos(float x);
long double acos(long double x);
float acosf(float x);
long double acosl(long double x);

The functions return the angle whose cosine is x, in the range [0, pi] radians. A domain error occurs if 1 < |x|.

double asin(double x);
float asin(float x);
long double asin(long double x);
float asinf(float x);
long double asinl(long double x);

The functions return the angle whose sine is x, in the range [-pi/2, +pi/2] radians. A domain error occurs if 1 < |x|.

double atan(double x);
float atan(float x);
long double atan(long double x);
float atanf(float x);
long double atanl(long double x);

The functions return the angle whose tangent is x, in the range [-pi/2, +pi/2] radians.

double atan2(double y, double x);
float atan2(float y, float x);
long double atan2(long double y, long double x);
float atan2f(float y, float x);
long double atan2l(long double y, long double x);

The functions return the angle whose tangent is y/x, in the full angular range [-pi, +pi] radians. A domain error occurs if both x and y are 0.

double cos(double x);
float cos(float x);
long double cos(long double x);
float cosf(float x);
long double cosl(long double x);

The functions return the cosine of x.

If x is large, the value returned might not be meaningful, but the function reports no error.

double sin(double x);
float sin(float x);
long double sin(long double x);
float sinf(float x);
long double sinl(long double x);

The functions return the sine of x.

If x is large, the value returned might not be meaningful, but the function reports no error.

double tan(double x);
float tan(float x);
long double tan(long double x);
float tanf(float x);
long double tanl(long double x);

The functions return the tangent of x.

If x is large, the value returned might not be meaningful, but the function reports no error.

12.7.9. Hyperbolic Functions

double acosh(double x);
float acosh(float x);
long double acosh(long double x);
float acoshf(float x);
long double acoshl(long double x);

The functions return the hyperbolic arccosine of x, in the range [0, infinity]. A domain error occurs if x < 1.

double asinh(double x);
float asinh(float x);
long double asinh(long double x);
float asinhf(float x);
long double asinhl(long double x);

The functions return the hyperbolic arcsine of x.

double atanh(double x);
float atanh(float x);
long double atanh(long double x);
float atanhf(float x);
long double atanhl(long double x);

The functions return the hyperbolic arctangent of x. A domain error occurs if x < -1 or +1 < x.

double cosh(double x);
float cosh(float x);
long double cosh(long double x);
float coshf(float x);
long double coshl(long double x);

The functions return the hyperbolic cosine of x.

double sinh(double x);
float sinh(float x);
long double sinh(long double x);
float sinhf(float x);
long double sinhl(long double x);

The functions return the hyperbolic sine of x.

double tanh(double x);
float tanh(float x);
long double tanh(long double x);
float tanhf(float x);
long double tanhl(long double x);

The functions return the hyperbolic tangent of x.

12.7.10. Exponential Functions

double exp(double x);
float exp(float x);
long double exp(long double x);
float expf(float x);
long double expl(long double x);

The functions return the exponential of x: ex.

double exp2(double x);
float exp2(float x);
long double exp2(long double x);
float exp2f(float x);
long double exp2l(long double x);

The functions return 2 raised to the power x: 2 x.

double expm1(double x);
float expm1(float x);
long double expm1(long double x);
float expm1f(float x);
long double expm1l(long double x);

The functions return one less than the exponential function of x: ex1.

12.7.11. Logarithms

double logb(double x);
float logb(float x);
long double logb(long double x);
float logbf(float x);
long double logbl(long double x);

The functions return the exponent e of x, as defined for the floating-point model (see Section 12.2.1).

Thus, |x·βlogb(x)| is always in the range [1, β).

int ilogb(double x);
int ilogb(float x);
int ilogb(long double x);
int ilogbf(float x);
int ilogbl(long double x);
#define FP_ILOGB0 < integer constant expression >
#define FP_ILOGBNAN < integer constant expression >

The functions return

  • The value of the macro FP_ILOGBNAN for x NaN

  • The value of the macro FP_ILOGB0 for x equal to 0

  • The value of the macro INT_MAX for x equal to positive or negative infinity

  • Otherwise, (int)logb(x)

double log(double x);
float log(float x);
long double log(long double x);
float logf(float x);
long double logl(long double x);

The functions return the natural logarithm of x. A domain error occurs if x < 0.

double log10(double x);
float log10(float x);
long double log10(long double x);
float log10f(float x);
long double log10l(long double x);

The functions return the base-10 logarithm of x. A domain error occurs if x < 0.

double log1p(double x);
float log1p(float x);
long double log1p(long double x);
float log1pf(float x);
long double log1pl(long double x);

The functions return the natural logarithm of 1 + x. A domain error occurs if x < -1.

double log2(double x);
float log2(float x);
long double log2(long double x);
float log2f(float x);
long double log2l(long double x);

The functions return the base-2 logarithm of x. A domain error occurs if x < 0.

12.7.12. Powers and Roots

double pow(double x, double y);
double pow(double x, int y);
float pow(float x, float y);
float pow(float x, int y);
long double pow(long double x, long double y);
long double pow(long double x, int y);
float powf(float x, float y);
long double powl(long double x, long double y);

The functions return x raised to the power y, xy.

double sqrt(double x);
float sqrt(float x);
long double sqrt(long double x);
float sqrtf(float x);
long double sqrtl(long double x);

The functions return the non-negative real square root of x: . A domain error occurs if x < 0.

double cbrt(double x);
float cbrt(float x);
long double cbrt(long double x);
float cbrtf(float x);
long double cbrtl(long double x);

The functions return the real cube root of x, x [image].

double hypot(double x, double y);
float hypot(float x, float y);
long double hypot(long double x, long double y);
float hypotf(float x, float y);
long double hypotl(long double x, long double y);

The functions return the square root of the sum of the squares of x and y, [image].

12.7.13. Scaling

double frexp(double x, int * pexp);
float frexp(float x, int * pexp);
long double frexp(long double x, int * pexp);
float frexpf(float x, int * pexp);
long double frexpl(long double x, int * pexp);

The functions determine a fraction frac and an exponent ex that represent the value of x. They return the value of frac and store the integer ex in *pexp, such that

  • |frac| is in the range [1/2, 1) or is 0

  • x == frac * 2ex

If x is 0, *pexp also is.

double ldexp(double x, int ex);
float ldexp(float x, int ex);
long double ldexp(long double x, int ex);
float ldexpf(float x, int ex);
long double ldexpl(long double x, int ex);

The functions return x * 2ex.

double modf(double x, double * pint);
float modf(float x, float * pint);
long double modf(long double x, long double * pint);
float modff(float x, float * pint);
long double modfl(long double x, long double * pint);

The functions determine an integer i and a fraction frac that represent the value of x. They return the value frac and store the integer i in *pint, such that

  • x == frac + i

  • |frac| is in the range [0, 1)

  • frac and i have the same sign as x

double scalbn(double x, int ex);
float scalbn(float x, int ex);
long double scalbn(long double x, int ex);
float scalbnf(float x, int ex);
long double scalbnl(long double x, int ex);

double scalbln(double x, long ex);
float scalbln(float x, long ex);
long double scalbln(long double x, long ex);
float scalblnf(float x, long ex);
long double scalblnl(long double x, long ex);

The functions return x * βex.

12.7.14. Value Manipulators

double copysign(double x, double y);
float copysign(float x, float y);
long double copysign(long double x, long double y);
float copysignf(float x, float y);
long double copysignl(long double x, long double y);

The functions return the magnitude of x with the sign of y.

double nan(const char * str);
float nan(const char *str);
long double nan(const char *str);
float nanf(const char *str);
long double nanl(const char *str);

The functions convert a null-terminated sequence beginning at str to a NaN code. The call nan("n-char-seq") effectively returns strtod("Nan (n-char-seq)", (char**)0) if the conversion succeeds; otherwise, it returns strtod("NAN").

double nextafter(double x, double y);
float nextafter(float x, float y);
long double nextafter(long double x, long double y);
float nextafterf(float x, float y);
long double nextafterl(long double x, long double y);

double nexttoward(double x, long double y);
float nexttoward(float x, long double y);
long double nexttoward(long double x, long double y);
float nexttowardf(float x, long double y);
long double nexttowardl(long double x, long double y);

The functions return

  • The next representable value after x if x < y

  • y if x == y

  • The next representable value before x if x > y

12.7.15. Floating Multiply-Add

double fma(double x, double y, double z);
float fma(float x, float y, float z);
long double fma(
    long double x, long double y, long double z);
float fmaf(float x, float y, float z);
long double fmal(
    long double x, long double y, long double z);

The functions return x * y + z to arbitrary intermediate precision.

#defineFP_FAST_FMA <integer constant expression>
#defineFP_FAST_FMAF <integer constant expression>
#defineFP_FAST_FMAL <integer constant expression>

Each of the macros is defined only if the call fma(x, y, z) executes about as fast as the expression x * y + z for arguments of type double, float, and long double, respectively.


Section 12.8. Mathematical Special Functions

12.8. Mathematical Special Functions

The TR1 library provides a number of advanced mathematical functions that operate on real floating-point values of type float, double, and long double. These functions are in the list of special functions specified in table 14 of [Int92].

Just as with the basic math functions (Section 12.7), the partial synopsis[17] of the header gives one signature; the function descriptions give all of the explicitly required overloads. Additional overloads are available as needed to satisfy the new overload rules (Section 12.6).

[17] The complete synopsis is in Appendix A.5.

12.8.1. Header <math.h> Synopsis

     // LAGUERRE POLYNOMIALS
double laguerre(unsigned n, double x);
double assoc_laguerre(unsigned n, unsigned m, double x);

  // LEGENDRE FUNCTIONS
double legendre(unsigned l, double x);
double assoc_legendre(unsigned l, unsigned m, double x);
double sph_legendre(unsigned l, unsigned m, double theta);

  // GAMMA FUNCTIONS
double lgamma(double x);
double tgamma(double x);

  // BETA FUNCTION
double beta(double x, double y);

  // ERROR FUNCTIONS
double erf(double x);
double erfc(double x);

  // ELLIPTIC INTEGRALS
double ellint_1(double k, double phi);
double ellint_2(double k, double phi);
double ellint_3(double k, double nu, double phi)
double comp_ellint_1(double k);
double comp_ellint_2(double k);
double comp_ellint_3(double k, double nu);

  // HYPERGEOMETRIC FUNCTIONS
double hyperg(double a, double b, double c, double x);
double conf_hyperg(double a, double c, double x);

  // BESSEL FUNCTIONS
double cyl_bessel_i(double nu, double x);
double cyl_bessel_j(double nu, double x);
double cyl_bessel_k(double nu, double x);
double sph_bessel(unsigned n, double x);

  // NEUMANN FUNCTIONS
double cyl_neumann(double nu, double x);
double sph_neumann(unsigned n, double x);

  // EXPONENTIAL INTEGRAL
double expint(double x);

  // HERMITE POLYNOMIALS
double hermite(unsigned n, double x);

  // ZETA FUNCTION
double riemann_zeta(double x);

12.8.2. Laguerre Polynomials

double laguerre(unsigned n, double x);
float laguerre(unsigned n, float x);
long double laguerre(unsigned n, long double x);
float laguerref(unsigned n, float x);
long double laguerrel(unsigned n, long double x);

The functions return the Laguerre polynomial of n and x, defined as

A domain error occurs if x < 0. The effect of calling this function is implementation defined if n >= 128.

double assoc_laguerre(unsigned n, unsigned m, double x);
float assoc_laguerre(unsigned n, unsigned m, float x);
long double assoc_laguerre(
  unsigned n, unsigned m, long double x);
float assoc_laguerref(unsigned n, unsigned m, float x);
long double assoc_laguerrel(
  unsigned n, unsigned m, long double x);

The functions return the associated Laguerre polynomial of n, m, and x, defined as

A domain error occurs if x < 0. The effect of calling this function is implementation defined if n >= 128.

12.8.3. Legendre Polynomials

double legendre(unsigned l, double x);
float legendre(unsigned l, float x);
long double legendre(unsigned l, long double x);
float legendref(unsigned l, float x);
long double legendrel(unsigned l, long double x);

The functions return the Legendre function of l and x, defined as

A domain error occurs if |x| > 1. The effect of calling this function is implementation defined if l >= 128.

double assoc_legendre(unsigned l, unsigned m, double x);
float assoc_legendre(unsigned l, unsigned m, float x);
long double assoc_legendre(
  unsigned l, unsigned m, long double x);
float assoc_legendref(unsigned l, unsigned m, float x);
long double assoc_legendrel(
  unsigned l, unsigned m, long double x);

The functions return the associated Legendre function of l, m, and x, defined as

A domain error occurs if x < 0. The effect of calling this function is implementation defined if l >= 128.

double sph_legendre(unsigned l, unsigned m, double theta);
float sph_legendre(unsigned l, unsigned m, float theta);
long double sph_legendre(
  unsigned l, unsigned m, long double theta);
float sph_legendref(unsigned l, unsigned m, float theta);
long double sph_legendrel(
  unsigned l, unsigned m, long double theta);

The functions return the spherical associated Legendre function of l, m, and theta, defined as [image], where

A domain error occurs if |m| > l. The effect of calling this function is implementation defined if l >= 128.

12.8.4. Gamma Functions

double tgamma(double x);
float tgamma(float x);
long double tgamma(long double x);
float tgamma(float x);
long double tgamma(long double x);

The functions return the gamma function of x, defined as

A domain error occurs if x is a negative integer or if x == 0 and the implementation cannot represent the result.

double lgamma(double x);
float lgamma(float x);
long double lgamma(long double x);
float lgamma(float x);
long double lgamma(long double x);

The functions return the logarithm of the absolute value of the gamma function of x. A domain error occurs if x <= 0.

12.8.5. Beta Function

double beta(double x, double y);
float beta(float x, float y);
long double beta(long double x, long double y);
float betaf(float x, float y);
long double betal(long double x, long double y);

The functions return the beta function of x and y, defined as

12.8.6. Error Functions

double erf(double x);
float erf(float x);
long double erf(long double x);
float erff(float x);
long double erfl(long double x);

The functions return the error function of x, defined as

double erfc(double x);
float erfc(float x);
long double erfc(long double x);
float erfcf(float x);
long double erfcl(long double x);

The functions return the complementary error function of x, defined as

12.8.7. Elliptic Integrals

double ellint_1(double k, double phi);
float ellint_1(float k, float phi);
long double ellint_1(long double k, long double phi);
float ellint_1f(float k, float phi);
long double ellint_1l(long double k, long double phi);

The functions return the incomplete elliptic integral of the first kind of k and phi, defined as

A domain error occurs if |k| > 1.

double ellint_2(double k, double phi);
float ellint_2(float k, float phi);
long double ellint_2(long double k, long double phi);
float ellint_2f(float k, float phi);
long double ellint_2l(long double k, long double phi);

The functions return the incomplete elliptic integral of the second kind of k and phi, defined as

A domain error occurs if |k| > 1.

double ellint_3(double k, double nu, double phi)
float ellint_3(float k, float nu, float phi)
long double ellint_3(
  long double k, long double nu, long double phi)
float ellint_3f(float k, float nu, float phi)
long double ellint_3l(
  long double k, long double nu, long double phi)

The functions return the incomplete elliptic integral of the second kind of nu, k, and phi, defined as

A domain error occurs if |k| > 1.

double comp_ellint_1(double k);
float comp_ellint_1(float k);
long double comp_ellint_1(long double k);
float comp_ellint_1f(float k);
long double comp_ellint_1l(long double k);

The functions return the complete elliptic integral of the first kind of k, defined as

double comp_ellint_2(double k);
float comp_ellint_2(float k);
long double comp_ellint_2(long double k);
float comp_ellint_2f(float k);
long double comp_ellint_2l(long double k);

The functions return the complete elliptic integral of the second kind of k, defined as

double comp_ellint_3(double k, double nu);
float comp_ellint_3(float k, float nu);
long double comp_ellint_3(long double k, long double nu);
float comp_ellint_3f(float k, float nu);
long double comp_ellint_3l(long double k, long double nu);

The functions return the complete elliptic integral of the third kind of k and n, defined as

12.8.8. Hypergeometric Functions

double hyperg(double a, double b, double c, double x);
float hypergf(float a, float b, float c, float x);
long double hypergl(long double a, long double b,
  long double c, long double x);
float hyperg(float a, float b, float c, float x);
long double hyperg(long double a, long double b,
  long double c, long double x);

The functions return the hypergeometric function of a, b, c, and x, defined as

double conf_hyperg(double a, double c, double x);
float conf_hyperg(float a, float c, float x);
long double conf_hyperg(
  long double a, long double c, long double x);
float conf_hypergf(float a, float c, float x);
long double conf_hypergl(
  long double a, long double c, long double x);

The functions return the confluent hypergeometric function of a, c, and x, defined as

12.8.9. Bessel Functions

double cyl_bessel_i(double nu, double x);
float cyl_bessel_i(float nu, float x);
long double cyl_bessel_i(long double nu, long double x);
float cyl_bessel_if(float nu, float x);
long double cyl_bessel_il(long double nu, long double x);

The functions return the regular modified cylindrical Bessel function of nu and x, defined as

A domain error occurs if x < 0. The effect of calling this function is implementation defined if nu >= 128.

double cyl_bessel_j(double nu, double x);
float cyl_bessel_j(float nu, float x);
long double cyl_bessel_j(long double nu, long double x);
float cyl_bessel_jf(float nu, float x);
long double cyl_bessel_jl(long double nu, long double x);

The functions return the cylindrical Bessel function of the first kind of nu and x, defined as

A domain error occurs if x < 0. The effect of calling this function is implementation defined if nu >= 128.

double cyl_bessel_k(double nu, double x);
float cyl_bessel_k(float nu, float x);
long double cyl_bessel_k(long double nu, long double x);
float cyl_bessel_kf(float nu, float x);
long double cyl_bessel_kl(long double nu, long double x);

The functions return the irregular modified cylindrical Bessel function of nu and x, defined as

A domain error occurs if x < 0. The effect of calling this function is implementation defined if nu >= 128.

double sph_bessel(unsigned n, double x);
float sph_bessel(unsigned n, float x);
long double sph_bessel(unsigned n, long double x);
float sph_besself(unsigned n, float x);
long double sph_bessell(unsigned n, long double x);

The functions return the spherical Bessel function of the first kind of n and x, defined as

A domain error occurs if x < 0. The effect of calling this function is implementation defined if n >= 128.

12.8.10. Neumann Functions

double cyl_neumann(double nu, double x);
float cyl_neumann(float nu, float x);
long double cyl_neumann(long double nu, long double x);
float cyl_neumannf(float nu, float x);
long double cyl_neumannl(long double nu, long double x);

The functions return the cylindrical Neumann function, also known as the cylindrical Bessel function of the second kind, of nu and x, defined as

A domain error occurs if x < 0. The effect of calling this function is implementation defined if n >= 128.

double sph_neumann(unsigned n, double x);
float sph_neumann(unsigned n, float x);
long double sph_neumann(unsigned n, long double x);
float sph_neumannf(unsigned n, float x);
long double sph_neumannl(unsigned n, long double x);

The functions return the spherical Neumann function, also known as the spherical Bessel function of the second kind, of n and x, defined as

A domain error occurs if x < 0. The effect of calling this function is implementation defined if n >= 128.

12.8.11. Exponential Integral

double expint(double x);
float expint(float x);
long double expint(long double x);
float expintf(float x);
long double expintl(long double x);

The functions return the exponential integral of x, defined as

12.8.12. Hermite Polynomials

double hermite(unsigned n, double x);
float hermite(unsigned n, float x);
long double hermite(unsigned n, long double x);
float hermitef(unsigned n, float x);
long double hermitel(unsigned n, long double x);

The functions return the Hermite polynomial of n and x, defined as

The effect of calling this function is implementation defined if n >= 128.

12.8.13. Zeta Function

double riemann_zeta(double x);
float riemann_zeta(float x);
long double riemann_zeta(long double x);
float riemann_zetaf(float x);
long double riemann_zetal(long double x);

The functions return the Riemann zeta function of x, defined as


Section 12.9. Functions of Complex Numbers

12.9. Functions of Complex Numbers

The synopsis of the header <complex.h> gives the declarations for the versions of the various functions that take arguments of type complex<double>.Each of these functions also has an overloaded version that takes arguments of type complex<float> and a version that takes arguments of type long double. In addition, three nonoverloaded functions have names usually consisting of the letter c followed by the name of the C++ function, followed by the letter f when the function takes arguments of type complex<float> or by the letter l when the function takes arguments of type complex<long double>. Finally, overloads are available as needed to satisfy the new overload rules (Section 12.6).

The headers <complex> and <ccomplex> also provides all these functions, with their names nested in the namespace std::tr1.

12.9.1. Header <math.h> Synopsis

  // ABSOLUTE VALUES
complex<double> abs(complex<double> x);
complex<double> fabs(complex<double> x);

  //  COMPONENTS
complex<double> arg(complex<double> x);
complex<double> imag(complex<double> x);
complex<double> real(complex<double> x);

  // TRIGONOMETRIC FUNCTIONS
complex<double> acos(complex<double> x);
complex<double> asin(complex<double> x);
complex<double> atan(complex<double> x);
complex<double> cos(complex<double> x);
complex<double> sin(complex<double> x);
complex<double> tan(complex<double> x);

  // HYPERBOLIC FUNCTIONS
complex<double> acosh(complex<double> x);
complex<double> asinh(complex<double> x);
complex<double> atanh(complex<double> x);
complex<double> cosh(complex<double> x);
complex<double> sinh(complex<double> x);
complex<double> tanh(complex<double> x);

  // EXPONENTIAL AND LOGARITHMIC FUNCTIONS
complex<double> exp(complex<double> x);
complex<double> log(complex<double> x);

  // POWERS AND ROOTS
complex<double> pow(complex<double> x, complex<double> y);
complex<double> sqrt(complex<double> x);

  // OTHER
complex<double> conj(complex<double> x);
complex<double> cproj(complex<double> x);

12.9.2. Absolute Values

double abs(complex<double> x);
float abs(complex<float> x);
long double abs(complex<long double> x);
double fabs(complex<double> x);
float fabs(complex<float> x);
long double fabs(complex<long double> x);
double cabs(complex<double> x);
float cabsf(complex<float> x);
long double cabsl(complex<long double> x);

The functions return the magnitude of x, |x|.

12.9.3. Components

double arg(complex<double> x);
float arg(complex<float> x);
long double arg(complex<long double> x);
double carg(complex<double> x);
float carg(complex<float> x);
long double carg(complex<long double> x);
float cargf(complex<float> x);
long double cargl(complex<long double> x);

The functions return the phase angle of x.

double imag(complex<double> x);
float imag(complex<float> x);
long double imag(complex<long double> x);
double cimag(complex<double> x);
float cimag(complex<float> x);
long double cimag(complex<long double> x);
float cimagf(complex<float> x);
long double cimagl(complex<long double> x);

The function returns the imaginary part of x.

double real(complex<double> x);
float real(complex<float> x);
long double real(complex<long double> x);
double creal(complex<double> x);
float creal(complex<float> x);
long double creal(complex<long double> x);
float crealf(complex<float> x);
long double creall(complex<long double> x);

The function returns the real part of x.

12.9.4. Trigonometric Functions

complex<double> acos(complex<double> x);
complex<float> acos(complex<float> x);
complex<long double> acos(complex<long double> x);
complex<double> cacos(complex<double> x);
complex<float> cacosf(complex<float> x);
complex<long> cacosl(complex<long double> x);

The functions return the angle whose cosine is x, with branch cuts outside the interval [-1, +1] on the real axis.

complex<double> asin(complex<double> x);
complex<float> asin(complex<float> x);
complex<long double> asin(complex<long double> x);
complex<double> casin(complex<double> x);
complex<float> casinf(complex<float> x);
complex<long> casinl(complex<long double> x);

The functions return the angle whose sine is x, with branch cuts outside the interval [-1, +1] on the real axis.

complex<double> atan(complex<double> x);
complex<float> atan(complex<float> x);
complex<long double> atan(complex<long double> x);
complex<double> catan(complex<double> x);
complex<float> catanf(complex<float> x);
complex<long> catanl(complex<long double> x);

The functions return the angle whose tangent is x, with branch cuts outside the interval [-i, +i] on the real axis.

complex<double> cos(complex<double> x);
complex<float> cos(complex<float> x);
complex<long double> cos(complex<long double> x);
complex<double> ccos(complex<double> x);
complex<float> ccosf(complex<float> x);
complex<long> ccosl(complex<long double> x);

The functions return the complex cosine of x.

complex<double> sin(complex<double> x);
complex<float> sin(complex<float> x);
complex<long double> sin(complex<long double> x);
complex<double> csin(complex<double> x);
complex<float> csinf(complex<float> x);
complex<long> csinl(complex<long double> x);

The functions return the complex sine of x.

complex<double> tan(complex<double> x);
complex<float> tan(complex<float> x);
complex<long double> tan(complex<long double> x);
complex<double> ctan(complex<double> x);
complex<float> ctanf(complex<float> x);
complex<long> ctanl(complex<long double> x);

The functions return the complex tangent of x.

12.9.5. Hyperbolic Functions

complex<double> acosh(complex<double> x);
complex<float> acosh(complex<float> x);
complex<long double> acosh(complex<long double> x);
complex<double> cacosh(complex<double> x);
complex<float> cacoshf(complex<float> x);
complex<long> cacoshl(complex<long double> x);

The functions return the inverse hyperbolic cosine of x, with a branch cut at values less than 1 along the real axis.

complex<double> asinh(complex<double> x);
complex<float> asinh(complex<float> x);
complex<long double> asinh(complex<long double> x);
complex<double> casinh(complex<double> x);
complex<float> casinhf(complex<float> x);
complex<long> casinhl(complex<long double> x);

The functions return the inverse hyperbolic sine of x, with branch cuts outside the interval [-i, +i] along the imaginary axis.

complex<double> atanh(complex<double> x);
complex<float> atanh(complex<float> x);
complex<long double> atanh(complex<long double> x);
complex<double> catanh(complex<double> x);
complex<float> catanhf(complex<float> x);
complex<long> catanhl(complex<long double> x);

The functions return the inverse hyperbolic tangent of x, with branch cuts outside the interval [-1, +1] along the real axis.

complex<double> cosh(complex<double> x);
complex<float> cosh(complex<float> x);
complex<long double> cosh(complex<long double> x);
complex<double> ccosh(complex<double> x);
complex<float> ccoshf(complex<float> x);
complex<long> ccoshl(complex<long double> x);

The functions return the complex hyperbolic cosine of x.

complex<double> sinh(complex<double> x);
complex<float> sinh(complex<float> x);
complex<long double> sinh(complex<long double> x);
complex<double> csinh(complex<double> x);
complex<float> csinhf(complex<float> x);
complex<long> csinhl(complex<long double> x);

The functions return the complex hyperbolic sine of x.

complex<double> tanh(complex<double> x);
complex<float> tanh(complex<float> x);
complex<long double> tanh(complex<long double> x);
complex<double> ctanh(complex<double> x);
complex<float> ctanhf(complex<float> x);
complex<long> ctanhl(complex<long double> x);

The functions return the complex hyperbolic tangent of x.

12.9.6. Exponential and Logarithmic Functions

complex<double> exp(complex<double> x);
complex<float> exp(complex<float> x);
complex<long double> exp(complex<long double> x);
complex<double> cexp(complex<double> x);
complex<float> cexpf(complex<float> x);
complex<long> cexpl(complex<long double> x);

The functions return the exponential of x, ex.

complex<double> log(complex<double> x);
complex<float> log(complex<float> x);
complex<long double> log(complex<long double> x);
complex<double> clog(complex<double> x);
complex<float> clogf(complex<float> x);
complex<long> clogl(complex<long double> x);

The functions return the natural logarithm of x, with a branch cut along the negative real axis.

12.9.7. Powers and Roots

complex<double> pow(complex<double> x, complex<double> y);
complex<float> pow(complex<float> x, complex<float> y);
complex<long double> pow(
complex<long double> x, complex<long double> y);
complex<double> cpow(complex<double> x, complex<double> y);
complex<float> cpowf(complex<float> x, complex<float> y);
complex<long> cpowl(
complex<long double> x, complex<long double> y);

The functions return x raised to the power y, xy.

complex<double> sqrt(complex<double> x);
complex<float> sqrt(complex<float> x);
complex<long double> sqrt(complex<long double> x);
complex<double> csqrt(complex<double> x);
complex<float> csqrtf(complex<float> x);
complex<long> csqrtl(complex<long double> x);

The functions return the complex square root of x, with a branch cut along the negative real axis.

12.9.8. Other Functions

complex<double> conj(complex<double> x);
complex<float> conj(complex<float> x);
complex<long double> conj(complex<long double> x);
complex<float> conjf(complex<float> x);
complex<long> conjl(complex<long double> x);

The functions return the complex conjugate of x, that is, the value of x in Cartesian coordinates, with the imaginary part negated.

complex<double> cproj(complex<double> x);
complex<float> cproj(complex<float> x);
complex<long double> cproj(complex<long double> x);
complex<float> cprojf(complex<float> x);
complex<long> cprojl(complex<long double> x);

The functions return a projection of x onto the Riemann sphere. Specifically, if either component of x is an infinity of either sign, the function returns a value whose real part is positive infinity and whose imaginary part is 0 with the same sign as the imaginary part of x. Otherwise, the function returns x.


Further Reading

  • What Every Computer Scientist Should Know About Floating-point Arithmetic [Gol91] is a good place to start if you're interested in how to use floating-point math.

  • The Art of Computer Programming [Knu98a, 214265] is, as usual, an outstanding reference.

  • The C/C++ Users Journal has a series of articles that I wrote [Bec00a, Bec00b, Bec00c, Bec00d] that provide a more gentle introduction.

  • IEC Standard 60559:19898, Binary Floating-Point Arithmetic for Microprocessor Systems [Int89] is the most commonly supported standard for floating-point math.

  • ISO Standard 31-11, Quantities and Units [Int92] contains the list of mathematical functions that is the basis for the special functions in the TR1 library.

  • ISO/IEC Standard 9899:1999, Programming LanguagesC [Int99] extends floating-point support in the C programming language.


Exercises

Exercise 1

Write a program that determines whether your implementation

  1. Sets errno

  2. Raises a floating-point exception

when a floating-point error occurs in the library functions.

Exercise 2

Check the results of the following function calls:

  1. fmod(1.0, 0.0)

  2. acosh(0.5)

  3. atan2(0.0, 0.0)

  4. log(-1.0)

  5. sqrt(-1.0)

  6. tgamma(-1.0)

  7. laguerre(1, -1.0)

  8. legendre(1, 2.0)

Exercise 3

Assume a floating-point representation with β = 10 and p = 3. Thus, normalized values can be represented in the usual exponential notation: .ddd x 10e. Also assume that the maximum allowable exponent is 9 and that the minimum allowable exponent is - 9.

  1. What are the normalized representations of the following values?

    1. .1

    2. 1

    3. 10

    4. 100

  2. What are the normalized representations of the values of the following expressions?

    1. .600 x 103 + .600 x 103

    2. .500 x 100 + .500 x 10-1

    3. .500 x 100 + .500 x 10-2

    4. .500 x 100 + .500 x 10-3

    5. .100 x 101 + .100 x 10x1

    6. .123 x 103 + .123 x 102

    7. .123 x 103 + .123 x 101

    8. .123 x 103 + .123 x 100

  3. Assuming that the floating-point representation does not support de-normalized values, what are the results of the following expressions?

    1. .123 x 10-8/.100 x 102

    2. .123 x 10-8/.100 x 103

    3. .123 x 10-8/.100 x 104

    4. .123 x 10-8/.100 x 105

  4. Assuming now that the floating-point representation does support de-normalized values, what are the results of the following expressions?

    1. .123 x 10-8/.100 x 102

    2. .123 x 10-8/.100 x 103

    3. .123 x 10-8/.100 x 104

    4. .123 x 10-8/.100 x 105

Exercise 4

Write a program that uses the macros defined in the header <float.h> (or <cfloat>) to determine the following properties of each of the three types float, double, long double for your implementation:

  1. The radix of the floating-point representation

  2. The number of digits, in base radix, in the significand

  3. The minimum and maximum exponents for nonzero normalized representable values

  4. The number of decimal digits representable in the significand

  5. The minimum positive representable value

  6. The maximum representable finite value

Exercise 5

Write a program that uses std::numeric_limits to determine the properties listed in the previous exercise.

Exercise 6

Write a program that computes the smallest value of type double that can be added to 1.0 to produce a value that is different from 1.0. Is this value the same as numeric_limits<double>::epsilon()? Should it be?

Exercise 7

Write a program that determines which of the standard rounding modes are supported by your implementation.

Exercise 8

Write a program that converts each of the values -1.5, -0.5, 0.5, and 1.5 to an integer value, using each of the rounding modes supported by your implementation. Explain the results.

Exercise 9

Write a program that rounds each of the values -1.5, -0.5, 0.5, and 1.5, using the default rounding mode and calling each of the functions ceil, floor, nearbyint, rint, lrint, llrint, round, lround, llround, and TRunc.

Exercise 10

Write a program that consists of the following functions:

  1. A function int dround(double) that uses the default rounding mode to return its argument rounded to an integer value

  2. A function int uround(double) that uses the function lrint to round its argument upward and return the result; on return the default rounding mode should be unchanged, even if an exception was thrown

  3. A main function that calls dround(1.1) and displays the result, then calls uround(1.1) and displays the result, and, finally, calls dround (1.1) again and displays the result

    Make sure that the two calls to dround return the same value.

Exercise 11

Write a program that determines which of the standard floating-point exceptions are supported by your implementation.

Exercise 12

Write a program that performs mathematical operations that raise each of the floating-point exceptions supported by your implementation and verifies that the exception was raised.

Exercise 13

Write a program containing a function that raises a floating-point exception of your choice and a second function that calls the first but guarantees that on return, all floating-point exceptions are cleared, even if the return is through a C++ exception. The main function should check that the floating-point exceptions are cleared.

Exercise 14

Write a program containing a function that raises a floating-point exception of your choice and a second function that calls the first but guarantees that on return, the floating-point status has been restored to its state on entry to the function, even if the return is through a C++ exception. The main function should check that the floating-point status is unchanged.

Exercise 15

Write a program containing a function that raises a floating-point exception of your choice and a second function that calls the first but defers raising of floating-point exceptions until it returns.

Exercise 16

Write a program containing a function that changes the rounding mode and raises a floating-point exception of your choice and a second function that calls the first but guarantees that on return, the floating-point status and the rounding mode have been restored to their states on entry to the function, even if the return is through a C++ exception. The main function should check that the floating-point status and the rounding mode are unchanged.

Exercise 17

Write a function template that returns a string object that holds "infinite", "not-a-number", "normal", "denormal", or "zero", depending on the value of its argument. Test it with the following values:

  1. 1.0

  2. 0.0 3. numeric_limits<double>::infinity()

  3. -numeric_limits<double>::infinity()

  4. numeric_limits<double>::quiet_NaN()

  5. numeric_limits<double>::denorm_min()

Exercise 18

Write a comparison function that takes two arguments of type double and imposes a strict weak ordering on all possible argument values. In particular, make sure that it handles NaN values consistently. Write a program that uses this function as the comparator for a std::set<double>, and verify that it works sensibly.

Exercise 19

What is the type of the returned value of each of the following function calls?

  1. abs(1)

  2. abs(1.0)

  3. cos(1)

  4. cos(1.0F)

  5. cos(1.0)

  6. cos(1.0L)

  7. cosf(1.0L)

  8. cosl(1)

  9. fmax(1.0, 2.0)

  10. fmax(1.0F, 2.0F)

  11. fmax(1.0F, 2.0)

  12. fmax(1, 2.0)

  13. fmax(1, 2.0F)

Write a program to verify your answers.


Chapter 13. Random Number Generators

The theory of probabilities is at bottom nothing but common sense reduced to calculation.

Théorie Analytique des Probabilities
PIERRE-SIMONE LAPLACE, TRANSLATED BY ANGELA PAO

Applications often need to generate numbers with varying degrees of unpredictability. For a card game, if players can predict the next card, the odds change. For a Monte Carlo integration,[1] if the selected input values show too strong a pattern, the value of the integral might not be accurate. For generating security keys, if a hacker can predict the generated keysperhaps with detailed knowledge of the key-generation algorithm security is compromised. Standard C and C++ offer the pair of functions rand and srand for generating streams of random numbers. The TR1 library offers several types for generating streams of uniformly distributed random numbers, as well as several other types for converting streams of uniformly distributed numbers into streams with other distributions.

[1] Or, more generally, for any simulation of a real-world process.

An engine is a class or template whose objects act as a source of random numbers uniformly distributed between a minimum and maximum value. A distribution is a class or template whose objects transform a stream of uniformly distributed random numbers obtained from an engine into a stream of random numbers with a particular distribution. An engine object can be passed directly to the function call operator of a distribution object to generate the next value in this stream, or an instance of the template variate_generator can be created to encapsulate an engine object and a distribution object in a single object. The random number generators in the TR1 library are described in the header <random>.

namespace std {
 namespace tr1 {

    // VARIATE GENERATOR
template<class Eng, class Dist> class variate_generator ;
    // SIMPLE ENGINES
template<class IType, IType a, IType c, IType m>
  class linear_congruential ;
template<class UType, int w, int n, int r,
  UType a, int u, int s,
  UType b, int t, UType c, int out_l> class mersenne_twister ;
template<class IType, IType m, int s, int r>
  class subtract_with_carry ;
template<class RType, int w, int s, int r>
  class subtract_with_carry_01 ;
class random_device ;

    // COMPOUND ENGINES
template<class Eng, int p, int r> class discard_block ;
template<class Eng1, int s1, class Eng2, int s2>
  class xor_combine ;

    // ENGINES WITH PREDEFINED PARAMETERS
typedef linear_congruential<sint, 16807, 0, 2147483647>
  minstd_rand0 ;
typedef linear_congruential<sint, 48271, 0, 2147483647>
  minstd_rand ;
typedef mersenne_twister<uint, 32, 624, 397, 31,
  0x9908b0df, 11, 7, 0x9d2c5680, 15, 0xefc60000, 18>
  mt19937 ;
typedef subtract_with_carry_01<float, 24, 10, 24>
  ranlux_base_01 ;
typedef subtract_with_carry_01<double, 24, 10, 48>
  ranlux64_base_01 ;
typedef discard_block<
  subtract_with_carry<i-type, 1 << 24, 10, 24>,
  223, 24> ranlux3 ;
typedef discard_block<
  subtract_with_carry<i-type, 1 << 24, 10, 24>,
  389, 24> ranlux4 ;
typedef discard_block<
  subtract_with_carry_01<float, 24, 10, 24>,
  223, 24> ranlux3_01 ;
typedef discard_block<
  subtract_with_carry_01<float, 24, 10, 24>,
  389, 24> ranlux4_01 ;

    // DISTRIBUTIONS
template<class IType = int>
  class uniform_int ;
template<class RType = double>
  class bernoulli_distribution ;
template<class IType = int, class RType = double>
  class geometric_distribution ;
template<class IType = int, class RType = double>
  class poisson_distribution ;
template<class IType = int, class RType = double>
  class binomial_distribution ;
template<class RType = double>
  class uniform_real ;
template<class RType = double>
  class exponential_distribution ;
template<class RType = double>
  class normal_distribution ;
template<class RType = double>
  class gamma_distribution ;

} };

The preceding synopsis and the sections that follow use template parameter names to designate particular sets of types, as follows.

  • IType: a signed integral type or an unsigned integral type, which must be one of short, int, long, unsigned short, unsigned int, or unsigned long

  • UType: an unsigned integral type, which must be one of unsigned short, unsigned int, or unsigned long

  • RType: a floating-point type, which must be one of float, double, or long double.

The TR1 library specification gives requirements for three categories of random number generators, referred to as uniform random number generators, random number engines,[2] and random distributions. We'll look at the requirements for random number engines in Section 13.1 and for random distributions in Section 13.5.

[2] The TR1 library calls these things pseudo-random number engines. However, since the other two categories also involve pseudo-random sequences, consistency dictates using either pseudo-random or random for all three.

A uniform random number generator has a function call operator that returns the next value in the random sequence, two member functions min and max that give the minimum and maximum values that can be generated, and a nested type name result_type that names the type returned by those three members. More formally, for every generator type Gen and object gen of type Gen, the following expressions must be valid.[3]

[3] This circumlocution avoids overspecifying these types. It's not significant here, but when we look at the requirements for an engine, for example, a more natural formulation might require a member function seed() and a member function seed(numeric-type ), but that would prohibit implementing these functions as a single function with a default argument.


Getting Values

  • Gen::result_type: the typedef is a synonym for the type of the expressions gen(), gen.min(), and gen.max().

  • gen.min(): the value of the expression is the minimum value returned by gen().

  • gen.max(): the value of the expression is the maximum value returned by gen(). When result_type is an integral type, this is the maximum value that can be returned;[4] when result_type is a floating-point type, this is the smallest value greater than all values that can be returned.[5]

    [4] That is, the result is in the closed range [min(), max()].

    [5] That is, the result is in the half-open range [min(), max()).

  • gen(): repeated invocations of the expression produce a sequence of random values between min() and max().

As we'll see, random number engines satisfy these requirements, so they can be used wherever a generator is required.


Section 13.1. Random Number Engines

13.1. Random Number Engines

A random number engine is a class or template whose objects act as a source of random numbers uniformly distributed between a minimum and maximum value. Engines are of two kinds. A simple engine produces random numbers directly. A compound engine obtains random numbers from one or more other engines and generates a stream of uniformly distributed random numbers from those values.[6]

[6] This sounds a lot like the definition of a distribution. The key difference is that a compound engine applies a specified algorithm to its input to produce its output values. A distribution produces values distributed in a particular way but without specifying the algorithm to use. Thus, every conforming implementation of a compound engine, given the same engine or engines for input, will produce the same sequence of values. This is not the case for distributions.

Different classes use different techniques to generate random numbers, but all engines that conform to the TR1 library specification provide several fundamental operations. You can set the state of the engine with constructors and the seed member functions, you can get the next value in the random sequence with the function call operator, and you can examine the range of values that can be generated, by calling the member functions min() and max().

Example 13.1. Basic Properties (random/engprops.cpp)

#include <random>
#include <iomanip>
#include <iostream>
using std::cout; using std::setw;

template <class Ty>
void show(const char *title, Ty value)
  { // show property title and value
  cout << setw (35) << title << ": " << value << '\n';
  }

unsigned trivial_seed ()
  { // trivial seed generator
  return 4;
  }

template <class Eng>
void show_properties(const char *name)
  { // show properties of engine type Eng
  cout << "\nProperties of " << name << '\n';
  Eng eng;
  show("Minimum", eng.min());
  show("Maximum", eng.max());
  show("Initial value", eng());
  eng.seed();
  show("After calling seed()", eng());
  Eng eng1(3);
  show("Constructed with Eng(3)", eng1());
  eng.seed(3);
  show("After calling seed(3)", eng());
  Eng eng2(trivial_seed);
  show("Constructed with Eng(trivial_seed)", eng2());
  eng.seed(trivial_seed);
  show("After calling seed(trivial_seed)", eng());
  }

int main()
  { // show properties of a few engines
  show_properties <std::tr1::minstd_rand>("minstd_rand");
  show_properties <std::tr1::ranlux_base_01>(
    "ranlux_base_01");
  return 0;
  }

In addition, you can write the state of an engine to an output stream with a stream inserter, and you can read the state from an input stream with a stream extractor. You can also compare two engines of the same type for equality.

Example 13.2. Reading and Writing (random/engrw.cpp)

#include <random>
#include <sstream>
#include <iostream>
using std::stringstream; using std::cout;

template <class Eng>
void readwrite()
  { // write and read engine state
  Eng eng, eng1;
  eng ();        // change state
  if (eng == eng1)
    cout << "Something's wrong\n";
  else
    cout << "Engines are not equal\n";

  stringstream str;
  str << eng;   // write state of eng
  str >> eng1;  // read state into eng1
  if (eng != eng1)
    cout << "Something's wrong\n";
  else
    cout << "Engines are equal\n";
  }

int main()
  { // demonstrate reading and writing engine states
  readwrite<std::tr1::mt19937>();
  return 0;
  }

More formally, for every engine type Eng and objects eng and eng1 of type Eng, the following expressions must be valid.

Setting the State

  • Eng(): the constructor constructs an object whose initial state is determined as if by calling seed().

  • Eng(x0), where x0 is a value of an integral type: the constructor constructs an object whose initial state is determined as if by calling seed(x0).

  • Eng(s), where s is a callable object (see Section 6.1) that takes no arguments and returns an unsigned integral value: the template constructor constructs an object whose initial state is determined as if by calling seed(s).

  • eng.seed(): the member function sets the internal state of the engine to a default value.

  • eng.seed(x0), where x0 is a value of an integral type: the member function sets the state of the generator to a value determined by x0.

  • eng.seed(s), where s is a callable object that takes no arguments and returns an unsigned integral type: the function sets the generator's internal state to values generated by successive calls to s().

Getting Values

  • The requirements are the same as for a generator, given earlier. For an engine object eng, the expression eng() returns values that are uniformly distributed between eng.min() and eng.max().

Reading, Writing, and Comparing

  • eng == eng1: true if eng and eng1 have the same state, so that the two objects will generate the same stream of values.

  • eng != eng1: TRue if eng == eng1 is false.

  • os << eng: sets the format flags of the output stream os to ios_-base::dec|ios_base::fixed|ios_base::left and sets the fill character to space, then writes the state of eng to the output streamwith one or more spaces separating adjacent numbersthen restores the format flags and fill character to their settings before the operation began.

  • is >> eng1: reads the new state of eng1 from the input stream is. The contents of the input stream must have been written by a call to os << eng, where eng is an engine of the same type as eng1, and os used the same locale, character type, and character traits type as is.[7]

    [7] Thus, eng == eng1 after executing os << eng followed immediately by is >> eng1.


Section 13.2. Engine Templates in the TR1 Library

13.2. Engine Templates in the TR1 Library

The TR1 library provides six templates that define engines. Sections 13.2.1 13.2.4 describe the basic engines; Sections 13.2.5 and 13.2.6, compound engines. The six templates satisfy all the requirements for engines, so you can use them as patterns if you write your own engine. You don't have to follow any of these patterns, though, so long as your engine provides all the required operations.

The library also provides a class named random_device (Section 13.3) and nine predefined engines, in the form of typedefs for particular template specializations (Section 13.4).

In the discussion that follows, some of the details are in the template declaration itself. In the text following the declaration, I'll explain the things that need more details than can easily fit in the declaration, including the details of the algorithm that the template implements and the contents of the engine's state.

Every engine has a state that is used to generate successive values. The size of an engine's state and its text representation, written by the stream inserter and read by the stream extractor, are exactly specified by TR1.[8] As a result, applications compiled with different implementations of the library and running on different hardware can share an engine's state. This is used for parallelizing calculations and for checkpointing. Parallelizing a calculation means distributing parts of the calculation to different processors, which requires being able to start an engine at a known state, even with a different implementation of that engine. Checkpointing means saving a long-running application's state periodically so that the calculation can be resumed on the same machine if it gets interrupted. This does not require portability across systems.

[8] Of course, this doesn't mean that every implementation must exactly follow these details, just that it must act as if it did. In particular, several of the TR1 engines can be implemented more efficiently by holding more state values than TR1 requires. However, in all cases, the text written to a stream must be as specified.

13.2.1. Basic Engine linear_congruential

template<class UType, UType A, UType C, UType M>
  class linear_congruential {
public:
  // engine interface
  typedef UType result_type;
  linear_congruential() { seed(); }
  explicit linear_congruential(unsigned long x0) { seed(x0); }
  template<class Seeder>
    linear_congruential (Seeder& s) { seed(s); }
  void seed(unsigned long x0 = 1);
  template<class Seeder>
    void seed(Seeder& s) { seed(s()); }
  result_type min() const;
  result_type max() const;
  result_type operator()();

  // type-specific members
  static const UType multiplier = A;
  static const UType increment = C;
  static const UType modulus = M;
  };

The class template describes a simple engine that produces values of type UType, using the recurrence relation xi=(A*xi-1+C) mod M.

If the value of the template argument M is 0, it is treated as if it were std::numeric_limits<UType>::max() + 1.[9] The type argument UType must be an unsigned integral type that is large enough to store values up to M - 1. The values of the template arguments A and C must be in the range [0, M-1].

The size of the engine's state is 1, and its value is the last value returned by operator() or, if no call has been made to operator(), the seed value.

The member function seed(unsigned long x0) sets the state of the engine to the value x0, unless x0 is 0 and C mod M is 0, in which case it sets the state to 1.[10]

[9] Conceptually, that is. That value can't be represented in an object of type UType.

[10] This avoids the degenerate case of a generator that produces nothing but 0 values.

This template implements the commonly used linear congruential algorithm. If you choose the template arguments carefully, it can produce long random sequences. If you choose badly, the sequences can be short, or they can show other patterns. The predefined generators minstd_rand0 (see Section 13.4.1) and minstd_rand (see Section 13.4.2) are well understood and have good properties.

Linear congruential engines as a rule are fast, especially if the value of M is the same as the size of an unsigned integral type, which avoids having to do the final division on most hardware. The implementation should use an efficient integral type to hold intermediate values when it computes a new value. However, if M is larger than the square root of the system's largest unsigned integral value, the engine can be quite slow, because the implementation may have to resort to multiple-precision arithmetic.

13.2.2. Basic Engine mersenne_twister

template<class UType, int W, int N, int R,
    UType A, int U, int S,
    UType B, int T, UType C, int L>
  class mersenne_twister {
public:
  // engine interface
  typedef UType result_type;
  mersenne_twister() { seed(); }
  explicit mersenne_twister(unsigned long x0) { seed(x0); }
  template<class Seeder>
    mersenne_twister(Seeder& s) { seed(s); }
  void seed();
  void seed(unsigned long x0 = 5489);
  template<class Seeder>
    void seed(Seeder& s);
  result_type min() const;
  result_type max() const;
  result_type operator()();

  // type-specific members
  static const int word_size = W;
  static const int state_size = N;
  static const int shift_size = M;
  static const int mask_bits = R;
  static const int UType parameter_a = A;
  static const int output_u = U;
  static const int output_s = S;
  static const UType output_b = B;
  static const int output_t = T;
  static const UType output_c = C;
  static const int output_l = L;
  };

The class template describes a simple engine that produces values of type UType by applying the following recurrence relation:

  • yi = (UM &xi-N)|(LM &xi-(N-1))

  • If the lowest bit of yi is set, xi = xi-(N-M) Λ(yi >>1)ΛA

  • Otherwise, xi = xi-(N-M) Λ(yi >>1)

then computing the result, o(xi), from the new value of xi, as follows:

  • z1i = xi Λ(xi >>U)

  • z2i = z1i Λ((z1i <<S)&B)

  • z3i = z2i Λ(z2i <<T)&C)

  • o(xi)= z3i Λ(z3i >>1)

where all the computations are performed modulo 2W, UM is a value of type UType with only its upper W-R bits set, and LM is a value of type UType with only its lower R bits set.

The type argument UType must be an unsigned integral type whose width is at least W bits; that is, it must be able to hold values up to 2W - 1. In addition:

  • 1 [image] M [image] N

  • 0 [image] R, U, S, T, L [image] W

  • 0 [image] A, B, C [image] 2 W - 1

The size of the engine's state is N, and its value is the sequence of values xiN, ...,xi1, in that order.

The member function seed(unsigned long x0) sets x-N to x0 mod 2W, then, iteratively, sets

x-N+i = [i+1812433253((x-N+i-1>>(W -2))Λ(x-N+i-1))] mod 2W

for i = 1 ...N - 1.

The template member function seed(Gen& g) sets the object's state to the successive values g() mod 2W, respectively.

The template implements the Mersenne Twister algorithm. The most commonly used version of the Mersenne Twister is implemented by mt19937 (see Section 13.4.3).

The algorithm is fast, but it has a large state, requiring N*W bits of storage.[11] An implementation typically updates all the state values at once, rather than changing them one at a time, as the algorithm specifies. This approach is faster, but it requires twice as much storage space.

[11] For example, the most common form of the Mersenne Twister, embodied in mt19937, requires 624 32-bit values to store its state.

13.2.3. Basic Engine subtract_with_carry

template<class IType, IType M, int S, int R>
  class subtract_with_carry {
public:
  // engine interface
  typedef IType result_type;
  subtract_with_carry() { seed(); }
  explicit subtract_with_carry(unsigned long x0) { seed(x0); }
  template<class Seeder>
    subtract_with_carry(Seeder& s) { seed(s); }
  void seed(unsigned long x0 = 19780503);
  template<class Seeder>
    void seed(Seeder& s);
  result_type min() const;
  result_type max() const;
  result_type operator()();

  // type-specific members
  static const IType modulus = M;
  static const int short_lag = S;
  static const int long_lag = R;
  };

The class template describes a simple engine that produces values of type IType by applying the recurrence relation xi = (xi-S - xi-R - cyi-1) mod M, where cyi = 1 if xi-S - xi-R - cyi-1 < 0; otherwise, cyi = 0.

The type argument IType must be an integral type large enough to hold values up to M. In addition, 0 < S < R.

The size of the engine's state is R, and its value is the sequence of values xi-R, ...,xi-1, cyi-1, in that order.

The member function seed(unsigned long x0) creates a generator object, lcg, of type linear_congruential<unsigned long, 2147483563, 40014, 0>. It initalizes it with the value x0 if x0 is not zero; otherwise, with the value 19780503. It then generates successive state values x-R,...,x-1 with lcg() mod M, then sets cy-1 to 1 if x-1 is 0; otherwise, to 0.

The member function template seed(Gen& g) accumulates unsigned 32-bit values produced by calling g() to generate successive state values x-R,...,x-1, then sets cy-1 to 1 if x-1 is 0, otherwise to 0. Formally, with N= [image] (M+31)/32 [image], the function uses g() to generate N*R successive values Z0,Z1,...,ZN*R-1 and initializes the engine's state x-R,...,x-1 to the values (Z0· 2 0+· · · +ZN-1· 232(N-1)) mod M, ...,(ZN*R-N 20+... +ZN*R-1 232(N-1)) mod M.

The engine generates values without multiplication, so it is quite fast.[12] With suitable lags, it generates pretty good random sequences. It can be improved significantly by discarding some of the generated values, as done by ranlux3(see Section 13.4.4) and ranlux4 (see Section 13.4.5).

[12] Don't worry about the modulus operation; mathematically, that requires division, but in fact, it's simply a test and a subtraction.

13.2.4. Basic Engine subtract_with_carry_01

template<class RType, IType W, int S, int R>
  class subtract_with_carry_01 {
public:
  // engine interface
  typedef RType result_type;
  subtract_with_carry_01() { seed(); }
  explicit subtract_with_carry_01 (unsigned long x0)
    { seed (x0); }
template<class Seeder>
  subtract_with_carry_01 (Seeder& s) { seed (s); }
void seed(unsigned long x0 = 19780503);
template<class Seeder>
  void seed(Seeder& s);
result_type min() const;
result_type max() const;
result_type operator() ();

// type-specific members
static const IType word_size = W;
static const int short_lag = S;
static const int long_lag = R;
};

The class template describes a simple engine that produces values of type RType by applying the recurrence relation xi = (xiS - xiR - cyi1) mod 1, where cyi = 2-W if xiS - xiR - cyi1 < 0; otherwise, cyi = 0.

The type argument RType must be a floating-point type with enough precision to hold all the bits in the generated values. In addition, 0 < S < R.

The size of the engine's state is R. With N = |(W + 31)/32 |, each value xi-k can be represented as (zk,0 + zk,1 ·2 32 + ... + zk,N1 ·232 (N-1))/2W . The textual representation of the state is the textual representation of the values zR,0, ...,zR,N-1, ...,z1,0, ...,z1,N-1,cyi-1 ·2W.

The member function seed(unsigned long x0) creates a generator object, lcg, of type linear_congruential<unsigned long, 2147483563, 40014, 0>. It initalizes it with the value x0 if x0 is not zero; otherwise, with the value 19780503. It then generates successive state values x-R, ...,x-1 with lcg()· 2W mod 1, then sets cy-1 to 2-W if x-1 is 0; otherwise, to 0.

The member function template seed(Gen& g) accumulates unsigned 32-bit values produced by calling g() to generate successive state values x-R, ...,x-1, then sets cy-1 to 2-W if x-1 is 0, otherwise to 0. Formally, with N= [image] (M+31)/32 [image], the function uses g() to generate N*R successive values Z0,Z1,...,ZN*R-1 and initializes the engine's state x-R,...,x-1 to the values (Z0·20+· · ·+ZN-1·232(N-1))·2-W mod 1,...,(ZN*R-N ·20+· · · +ZN*R-1 232(N-1)) 2-W mod 1.

The engine generates floating-point values in the range [0.0, 1.0). If you wade through the details of the specification, you'll see that with a binary floating-point implementation, the returned values have no more than W bits in their fraction. Other floating-point representations may need more bits but must return the same values as the binary representation.

Just like subtract_with_carry, this algorithm is quite fast. Its predefined versions are ranlux_base_01 (Section 13.4.6) and ranlux64_base_01(Section 13.4.7). Also like subtract_with_carry, with suitable lags, it generates pretty good random sequences, which can be improved by discarding some of the values, as done by ranlux3_01 (see Section 13.4.8) and ranlux4_01 (see Section 13.4.9).

13.2.5. Compound Engine discard_block

template<class Eng, int P, int R>
  class discard_block {
public:
  // engine interface
  typedef typename base_type::result_type result_type;
  discard_block() : eng(), n(0) {}
  explicit discard_block(const base_type& e)
    : eng(e), n(0) {}
  explicit discard_block(unsigned long x0)
    : eng(x0), n(0) {}
  template<class Gen>
    discard_block (Gen& g) : eng(g), n(0) {}
  void seed() { eng. seed(); }
  template<class Gen>
    void seed(Gen& g) { eng.seed (g); }
  const base_type& base() const { return eng; }
  result_type min() const { return eng.min(); }
  result_type max() const { return eng.max(); }
  result_type operator()();

  // type-specific members
  typedef Eng base_type;
  static const int block_size = P;
  static const int used_block = R;

  // exposition only:
private:
  Eng eng;
  int n;
  };

The class template describes a compound engine whose operator() returns the first P values returned by the engine eng, then discards the next P - R values returned by eng, and then repeats this cycle as necessary.

The type argument Eng must be an engine type that satisfies the requirements set out at the beginning of this chapter. In addition, 0 < R <= P.[13]

The size of the engine's state is one more than the size of eng's state. Its textual representation is the textual representation of eng, followed by the textual representation of the number of calls to operator() since the beginning of the current cycle.

[13] The TR requires 0 <= R <= P, but passing 0 for the template argument R has the same effect as passing 1. There's no benefit from using 0.

The engine can sometimes be used to improve the quality of another engine.[14] See, for example, ranlux3 (Section 13.4.4), ranlux4 (Section 13.4.5), ranlux3_01 (Section 13.4.8), and ranlux4_01 (Section 13.4.9).

[14] But heed Knuth's warning that modifying random number generators often makes them worse. See [Knu98a, 26].

13.2.6. Compound Engine xor_combine

template<class Eng1, int S1, class Eng2, int S2>
  class xor_combine {
public:
  // engine interface
  typedef see below result_type;
  xor_combine() : eng1 (), eng2() {}
  xor_combine (const base1_type& e1, const base2_type& e2)
     : eng1 (e1), eng2 (e2) {}
  xor_combine(unsigned long x0) : eng1 (x0), eng2 (x0 + 1) {}
  template <class Gen>
     xor_combine(Gen& g) : eng1(g), eng2(g) {}
  void seed() { eng1.seed(); eng2.seed(); }
  template<class Gen>
    void seed(Gen& g) { eng1.seed(g); eng2.seed(g); }
  const base1_type& base1() const { return eng1; }
  const base2_type& base2() const { return eng2; }
  result_type min() const;
  result_type max() const;
  result_type operator()();
  // type-specific members
  typedef Eng1 base1_type;
  typedef Eng2 base2_type;
  static const int shift1 = S1;
  static const int shift2 = S2;

  // exposition only:
private:
  Eng1 eng1;
  Eng2 eng2;
  };

The class template describes a compound engine whose operator() returns (eng1() << shift1) Λ (eng2() << shift2).

The type arguments Eng1 and Eng2 must be engine types that satisfy the requirements set out at the beginning of this chapter. Each type's nested member typedef result_type must be an integral type. The template's nested type xor_combine::result_type is the one of those two nested types that provides the most storage. In addition, 0 <= s1 and 0 <= s2.

The size of the engine's state is the sum of the sizes of the states of eng1 and eng2. Its textual representation is the textual representation of eng1, followed by the textual representation of eng2.

The engine combines the results of two engines, using left shifts and bitwise exclusive OR. Except in unusual circumstances, at least one of the two shift values should be 0. For best results, the engine whose value is not shifted should produce values ranging from 0 to 2n - 1, and the shifted values from the other engine should be somewhere in that range.


Section 13.3. TR1 Library Class random_device

13.3. TR1 Library Class random_device

This class draws random numbers from a system-supplied source, if there is one.

class random_device {
public:
  // engine interface
  typedef unsigned int result_type;
  explicit random_device(
    const std :: string& token = str0);
      // str0 is implementation-defined
  result_type min() const;
  result_type max() const;
  result_type operator()();

  // type-specific members
  double entropy() const;
  };

The class describes an engine that produces nondeterministic sequences of random numbers on platforms on which this can be done. On platforms on which this can't be done, it uses an unspecified random number generator.

The default value and the meaning of the constructor argument token are defined by the implementation. The constructor throws an exception object of a type that is derived from std::exception if the random_-device object cannot be initialized.

The member functions min and max return the values 0 and numeric_-limits<result_type>::max(), respectively.

The member function operator() returns a random value. The returned values are uniformly distributed in the closed range [min(), max()]. The operator throws an exception object of a type that is derived from std:: exception if a random number cannot be obtained.

The member function entropy returns a value between min() and the base 2 logarithm of (max() + 1) that represents an estimate of the entropy of the random numbers. If the class uses a random number generator, the function returns 0.


Section 13.4. Predefined Engines in the TR1 Library

13.4. Predefined Engines in the TR1 Library

The TR1 library provides nine predefined engines. These engines, in the form of typedefs for particular template specializations, represent some of the most commonly used random number generators. For most of the predefined engines, the specification gives the ten-thousandth value returned by the function call operator for a default constructed object. This value can be used to check whether the template and the specialization have been implemented correctly.

13.4.1. minstd_rand0

typedef linear_congruential<uint, 16807, 0, 2147483647>
  minstd_rand0 ;

The type uint is an implementation-defined unsigned integral type, large enough to hold values in the range [0, 2147483657].

x10,000 = 1,043,618,065.

13.4.2. minstd_rand

typedef linear_congruential<uint, 48271, 0, 2147483647>
  minstd_rand ;

The type uint is an implementation-defined unsigned integral type, large enough to hold values in the range [0, 2147483657].

x10,000 = 399,268,537.

13.4.3. mt19937

typedef mersenne_twister<uint, 32, 624, 397, 31,
  0x9908b0df, 11, 7, 0 x9d2c5680, 15, 0 xefc60000, 18>
  mt19937 ;

The type uint is an implementation-defined unsigned integral type that is at least 32 bits wide.

x10,000 = 4,123,659,995.

13.4.4. ranlux3

typedef discard_block<
  subtract_with_carry< sint, 1 << 24, 10, 24>,
  223, 24> ranlux3 ;

The type sint is an implementation-defined signed integral type with at least 24 value bits.

x10,000 = 5,957,620.

13.4.5. ranlux4

typedef discard_block <
  subtract_with_carry < sint, 1 < < 24, 10, 24 >,
  389, 24 > ranlux4 ;

The type sint is an implementation-defined signed integral type with at least 24 value bits.

x10,000 = 8,587,295.

13.4.6. ranlux_base_01

typedef subtract_with_carry_01 < float, 24, 10, 24 >
  ranlux_base_01 ;

13.4.7. ranlux64_base_01

typedef subtract_with_carry_01 < double, 48, 10, 24 >
  ranlux64_base_01 ;

13.4.8. ranlux3_01

typedef discard_block <
  subtract_with_carry_01 < float, 24, 10, 24 >, 223, 24 >
  ranlux3_01 ;

x10,000 = 5,957,620.2-24.

13.4.9. ranlux4_01

typedef discard_block <
  subtract_with_carry_01 < float, 24, 10, 24 >, 389, 24 >
  ranlux4_01 ;

x10,000 = 8,587,295.2- 24.


Section 13.5. Random Number Distributions

13.5. Random Number Distributions

A random number distribution is a class or a template whose objects transform a stream of uniformly distributed random numbers obtained from an engine into a stream of random numbers with a particular distribution. Distributions can be either discrete or continuous. A discrete distribution describes random numbers chosen from a countable set of possible values. Although the size of that set can be infinite, it is much more common for it to be finite. The most obvious example is tossing a coin; the set of possible values is heads and tails. Discrete distributions in the TR1 library return integer values. A continuous distribution describes random numbers chosen from a continuous range of possible values. For example, the time between particle emissions in radioactive decay is random, with an exponential distribution. Continuous distributions in the TR1 library return floating-point values.[15]

[15] Yes, technically, floating-point values aren't really continuous and could be considered discrete. But for computational purposes, floating-point numbers are close enough to continuous that, with a bit of care, we can treat them as continuous. That's important, because we use them to model real-world processes that are, above the quantum level, continuous.

A random number distribution that conforms to the TR1 library specification provides only a few fundamental operations: You can get the next value in the random sequence, discard any internal state values that the distribution may be using, write the state of a distribution to an output stream with a stream inserter, and read the state from an input stream with a stream extractor.

Example 13.3. Basic Properties (random/distprops.cpp)

#include <random>
#include <iostream>
#include <sstream>
using std::tr1::normal_distribution;
using std::tr1::ranlux64_base_01;
using std::stringstream; using std::cout;
  int main()
  { // show properties of a distribution
  ranlux64_base_01 eng;
  normal_distribution <> dist;
  stringstream str;
  std::cout << "First value: " << dist(eng) << '\n';
  str<< eng << ' ' << dist;
  std::cout << "Second value: " << dist(eng) << '\n';
  str >> eng >> dist;
  std::cout << "Second value, after read: "
    << dist(eng) << '\n';
  str.clear();
  str.seekg (0);
  str >> eng >> dist;
  dist.reset ();
  std::cout << "Second value, after reset: "
    << dist(eng) << '\n';
  return 0;
  }

More formally, for every distribution type Dist and object dist of type Dist, the following expressions must be valid.

Getting Values

  • Dist::input_type: the typedef is a synonym for the type that the engine passed to the distribution's operator() must return.

  • Dist::result_type: the typedef is a synonym for the type returned by the distribution's operator().

  • dist(gen): repeated invocations of the expression produce a sequence of random values distributed according to the definition of the particular distribution. The object gen must be an object of a type that implements the requirements for a generator, and the expression gen() must return values of type Dist::input_type. If Dist::input_type is a floating-point type, the expression gen() must return values in the closed range [0.0, 1.0].[16]

    [16] If you need to use a generator that doesn't return values in this range, you can adjust the result with variate_generator (see Section 13.8).

Reading, Writing, and Resetting

  • os << dist: writes the state of dist to the output stream os.

  • is >> dist1: reads the new state of dist1 from the input stream is.[17]

    [17] Unlike engines, distributions cannot be written and read portably. The details of writing and reading are implementation specific. This means that you can use a distribution's inserter and extractor for checkpointing but not for parallelizing (see Section 13.2).

  • dist.reset(): discards any internal state that the distribution maintains.

The TR1 library specification does not have any requirements for states of distributions, [18] and many distributions do not have any internal state. Still, it's a good habit to always call reset when you've been using a distribution object with one engine object and change to a different engine object or reseed the original engine object. That will ensure that you discard any leftovers from the previous engine.

[18] So in the preceding example, it's possible that the last two generated numbers will be the same.

The distributions in the TR1 library all have member functions that return the values of the arguments passed to an object's constructor. This is not required for distributions in general. However, it's a good idea to do the same in distributions that you write.


Section 13.6. Discrete Distributions

13.6. Discrete Distributions

The specifications for the discrete distributions in the TR1 library give the probability of each possible value. The formula p(i)= ... means that the probability of getting the value i is given by the expression on the right-hand side of the equals sign.

13.6.1. bernoulli_distribution

template < class RType = double >
  class bernoulli_distribution {
public :
  // distribution interface
  typedef int input_type ;
  typedef bool result_type ;
  explicit bernoulli_distribution (
    const RType & P0 = RType (0.5))
    : P( P0) {}
  void reset ();
  template < class Eng >
    bool operator() ( Eng & eng);

  // type-specific members
  RType p () const { return P ; }

  // exposition only:
private :
  RType P;
  };

p(T)= P

p(F)= 1 - P

The value of the constructor argument P0 must be in the closed range [0.0, 1.0]. In a call to operator() on a bernoulli_distribution object, the type Eng of the argument eng must be an engine whose operator() returns int.

Instances of the template bernoulli_distribution produce sequences of random values true and false, with the probability of true equal to the stored value P.

13.6.2. binomial_distribution

template < class IType = int, class RType = double >
  class  binomial_distribution {
public :
  // distribution interface
  typedef  /*  implementation  defined  */  input_type ;
  typedef IType result_type ;
  explicit  binomial_distribution (
    IType T0 = 1, const RType & P0 = RType (0.5))
    : T(T0), P(P0) {}
  void reset ();
  template < class  Eng >
    result_type operator() ( Eng & eng);
  // type-specific members
  IType t () const { return T; }
  RType p () const { return P; }

  // exposition only:
private :
  IType  T;
  RType  P;
  };

The value of the constructor argument T0 must be greater than or equal to 0. The value of the constructor argument P0 must be in the closed range [0.0, 1.0]. In a call to operator() on a binomial_distribution object, the type Eng of the argument eng must be an engine whose operator() returns int.

Instances of the template binomial_distribution produce random sequences of values of type IType in the closed range [0, T]. For an event whose probability of success is P, each value I in the random sequence occurs with probability equal to the probability of getting success exactly I times in T trials.

13.6.3. geometric_distribution

template < class IType = int, class RType = double >
  class  geometric_distribution {
public :
  // distribution interface
  typedef RType input_type ;
  typedef IType result_type ;
  explicit geometric_distribution (
    const RType & P0 = RType (0.5))
    : P(P0) {}
  void reset ();
  template < class Eng >
    result_type operator() ( Eng & eng);

  // type-specific members
  RType p () const { return P; }

  // exposition only:
private :
  RType P;
  };

p(i)=(1-P) Pi-1

The value of the constructor argument P0 must be in the open range (0.0, 1.0). In a call to operator() on a geometric_distribution object, the type Eng of the argument eng must be an engine whose operator() returns RType.

Instances of the template geometric_distribution produce sequences of random values of type IType, all of which are greater than or equal to 1. For an event whose probability of success is P, each value I in the random sequence occurs with probability equal to the probability of getting the first success on the Ith trial.

13.6.4. poisson_distribution

template < class IType = int, class RType = double >
  class poisson_distribution {
public :
  // distribution interface
  typedef RType input_type ;
  typedef IType result_type ;
  explicit poisson_distribution ( const RType & M0 = RType (1))
    : M( M0) {}
  void reset ();
  template < class Eng >
    result_type operator() ( Eng & eng);

  // type-specific members
  RType mean () const { return M ; }

  // exposition only:
private :
  RType M;
  };

The value of the constructor argument M0 must be greater than 0. In a call to operator() on a poisson_distribution object, the type Eng of the argument eng must be an engine whose operator() returns RType.

Instances of the template poisson_distribution produce random sequences of values of type IType, all of which are greater than or equal to 0. For an event that occurs at intervals whose average duration is M, each value I in the random sequence occurs with probability equal to the probability that I events will occur in an interval of duration M.

13.6.5. uniform_int

template < class IType = int >
  class uniform_int {
public :
  // distribution interface
  typedef IType input_type ;
  tpyedef IType result_type ;
  explicit uniform_int ( IType min0 = 0, IType max0 = 9)
    : N( min0), X( max0) {}
  void reset ();
  template < class Eng >
    result_type operator() ( Eng & eng);

  // type-specific members
  template < class Eng >
    result_type operator() ( Eng & eng, result_type mx);
  result_type min () const { return N ; }
  result_type max () const { return X ; }

  // exposition only:
private :
  IType N;
  IType X;
  };

The value of the constructor argument min0 must be less than or equal to the value of the constructor argument max0. In a call to operator() on a uniform_int object, the type Eng of the argument eng must be an engine whose operator() returns IType.

The values returned by calls to operator()(eng) will be uniformly distributed in the closed range [N, X]. The values returned by calls to operator()(eng, val) will be uniformly distributed in the half-open range [0, val).

Instances of the template uniform_int produce uniformly distributed random sequences of values of type IType, all of whose values are greater than or equal to the specified minimum value and less than or equal to the specified maximum value. Further, the function call operator that takes two arguments produces random sequences all of whose values are greater than or equal to the specified minimum value and strictly less than the value of the second argument.[19]

[19] This allows use of uniform_int objects with such algorithms as std::random_shuffle, which change the desired range as they progress through their data.


Section 13.7. Continuous Distributions

13.7. Continuous Distributions

The specifications for the continuous distributions in the TR1 library give the probability density function for the distribution. Given a probability density function p(x), the probability that a result will be in the closed range [a,b] is [image].

As mentioned earlier, the engine that you pass to the function call operator of a continuous distribution must return values in the closed range [0.0, 1.0].

13.7.1. exponential_distribution

template < class RType = double >
  class exponential_distribution {
public :
  // distribution interface
  typedef RType input_type ;
  typedef RType result_type ;
  explicit exponential_distribution (
    const result_type & L0 = result_type (1)) : L( L0) {}
  void reset ();
  template < class Eng >
    result_type operator() ( Eng & eng);
  // type-specific members
  RType lambda () const { return L ; }

  // exposition only:
private :
  RType L;
  };

p(x)= λe-λx

The stored value L is the value of λ in the probability density function p(x).

The value of the constructor argument L0 must be greater than 0. In a call to operator() on an exponential_distribution object, the type Eng of the argument eng must be an engine whose operator() returns RType.

Instances of the template exponential_distribution produce random sequences of values of type Rtype, all of which are greater than 0. For a process whose state changes at intervals whose average duration is L, values within the random sequence in the interval x,x + Δx occur with probability equal to the probability that the process will change state within an interval whose duration is between x and x + Δx.

13.7.2. gamma_distribution

template < class RType = double >
  class gamma_distribution {
public :
  // distribution interface
  typedef RType input_type ;
  typedef RType result_type ;
  explicit gamma_distribution (
    const result_type & a0 = result_type (1)) : A( A0) {}
  void reset ();
  template < class Eng >
    result_type operator() ( Eng & eng);

  // type-specific members
  RType alpha () const { return A ; }
  // exposition only:
private :
  RType A;
  };

The stored value A is the value of α in the probability density function p(x).

The value of the constructor argument A0 must be greater than 0. In a call to operator() on a gamma_distribution object, the type Eng of the argument eng must be an engine whose operator() returns RType.

Instances of the template gamma_distribution produce random sequences of values of type Rtype, all of which are greater than 0. For a process whose state changes at intervals whose average duration is 1, and when A is an integer, values within the random sequence in the interval x,x + Δx occur with probability equal to the probability that the process will change state A times within an interval whose duration is between x and x + Δx.[20] Thus, values in the sequence generated by an instance of the template gamma_distribution with A == 1 will have the same distribution as values in the sequence generated by an instance of the template exponential_distribution with L == 1.

[20] The meaning of a nonintegral number of state changes (i.e., A not an integer) is left to philosophers.

13.7.3. normal_distribution

template < class RType = double >
  class normal_distribution {
public :
  // distribution interface
  typedef RType input_type ;
  typedef RType result_type ;
  explicit normal_distribution (
    const result_type & M0 = 0, const result_type & S0 = 1)
       : M(M0), S(S0) {}
  void reset ();
  template < class Eng >
    result_type operator() ( Eng & eng);

  // type-specific members
  RType mean () const { return M ; }
  RType sigma () const { return S ; }

  // exposition only:
private :
  RType M;
  RType S;
  };

The stored value S is the values of σ in the probability density function p(x).

The value of the constructor argument S0 must be greater than 0. In a call to operator() on a normal_distribution object, the type Eng of the argument eng must be an engine whose operator() returns RType.

Instances of the template normal_distribution produce random sequences of values of type RType. The values occur with probabilities given by the normal distribution with mean value M and variance S*S.

13.7.4. uniform_real

template < class RType = double >
  class uniform_real {
public :
  // distribution interface
  typedef RType input_type ;
  tpyedef RType result_type ;
  explicit uniform_real (
    RType min0 = RType (0), RType max0 = RType (1))
      : N( min0), X( max0) {}
  void reset ();
  template < class Eng >
    result_type operator() ( Eng & eng);
  // type-specific members
  result_type min () const { return N ; }
  result_type max () const { return X ; }

  // exposition only:
private :
  RType N;
  RType X;
  };

The value of the constructor argument min0 must be less than the value of the constructor argument max0.[21] In a call to operator() on a uniform_-real object, the type Eng of the argument eng must be an engine whose operator() returns RType.

The values returned by calls to operator()(eng) will be uniformly distributed in the half-open range [N,X).

[21] The TR1 library specification says that min0 must be less than or equal to max0. That's not right, because the distribution returns values that are strictly less than max0. If min0 and max0 were equal, the distribution could not return any values.

Instances of the template uniform_real produce uniformly distributed random sequences of values of type RType, all of whose values are greater than or equal to the specified minimum value and less than the specified maximum value.


Section 13.8. The variate_generator Class Template

13.8. The variate_generator Class Template

As we've seen, the generator object that you pass to a distribution's operator() must return the exact type that the distribution expects. In addition, when that type is a floating-point type, the values returned by the generator must be in the closed range [0.0, 1.0]. If you need to use a generator that doesn't meet these constraints, or if you want to consolidate a generator and a distribution into a single object, use the class template variate_generator.

template < class Generator, class Dist >
  class variate_generator {
public :
  // generator interface
  typedef typename Dist :: result_type result_type ;
  result_type operator() ();
  result_type min () const { return D. min (); }
  result_type max () const { return D. max (); }

  // type-specific members
  variate_generator ( engine_type G0,
     distribution_type D0) : G(G0), D(D0) {}
  template < class T >
    result_type operator() (T value);
  typedef Generator engine_type ;
  typedef Gen engine_value_type ;
  typedef Dist distribution_type ;
  engine_value_type & engine ()
    { return G ; }
  const engine_value_type & engine () const
    { return G ; }
  distribution_type & distribution ()
    { return D ; }
  const distribution_type & distribution () const
    { return D ; }

  // exposition only:
private :
  Gen G;
  Dist D;
  };

The template type argument Generator must name a generator type, Gen, or a pointer or reference to a generator type, Gen* or Gen&. The nested typedef engine_value_type is a synonym for the underlying generator type Gen.

The class template effectively creates a wrapper object WG that transforms the values returned by G() as follows:

  • If Gen::result_type and Dist::result_type are both integral types, WG() returns G().

  • If Gen::result_type is an integral type and Dist::result_type is a floating-point type, WG() returns Dist::result_type(G())/ (G.max() - G.min() + 1).

  • If Dist::result_type is an integral type and Gen::result_type is a floating-point type, WG() returns the result of an implementation-defined transformation of G().

  • If Gen::result_type and Dist::result_type are both floating-point types, WG() returns Dist::result_type(G()) / (G.max() - G.min()).

The member operator()() returns D(WG). The member operator()(T value) returns D(WG, value).

To combine an engine and a generator, you pass the type of the engine and the type of the distribution as arguments to the variate_generator template. Then you create a variate_generator object, passing an engine object and a distribution object to the constructor. Once you've created a variate_generator object, you can manipulate its stored engine and distribution objects directly through the member functions engine and distribution.

Example 13.4. Simple variate_generator Object (random/variate.cpp)

#include <random>
#include <iomanip>
#include <iostream>
#include <array>
using std::tr1::variate_generator;
using std::tr1::ranlux3_01;
using std::tr1::gamma_distribution;
using std::tr1::array;
using std::cout; using std::setw; using std::left;

typedef ranlux3_01 eng_t;
typedef gamma_distribution <> dist_t ;
typedef variate_generator <eng_t, dist_t > gen_t;

const int nvals = 10;

int main()
  { // demonstrate variate generator
  eng_t eng;
  dist_t dist;
  gen_t gen(eng, dist);
  array <gen_t::result_type,nvals > res0, res1;
  for (int i = 0; i < nvals ; ++i)
    res0[i] = dist(eng);

  for (int i = 0; i < nvals; ++i)
    res1[i] = gen();

  cout << "Part 1\n" << left;
  for (int i = 0; i < nvals ; ++i)
    cout << setw (12) << res0[i] << ' '
      << setw (12) << res1[i] << '\n';

  // restart
  eng.seed();
  dist.reset();
  for (int i = 0; i < nvals ; ++i)
    res0[i] = dist(eng);

  gen.engine().seed();
  gen.distribution().reset();
  for (int i = 0; i < nvals; ++i)
    res1[i] = gen();

  cout << "\nPart2\n";
  for (int i = 0; i < nvals ; ++i)
    cout << setw(12) << res0[i] << ' '
      << setw(12) << res1[i] << '\n';
  return 0;
  }

In Part 1 of the preceding example, note that the pairs of values displayed in each line are the same. The engines and distributions used by dist(eng) and gen start in the same state, so they generate the same sequence of values. Part 2 reseeds both engines and resets both distributions, so they again produce the same pairs of values.

You can also create a variate_generator object that holds a pointer or a reference to its engine.

Example 13.5. variate_generator with Reference (random/varref.cpp)

#include <random>
#include <iomanip>
#include <iostream>
#include <array>
using std::tr1::variate_generator;
using std::tr1::ranlux3_01;
using std::tr1::gamma_distribution;
using std::tr1::array;
using std::cout; using std::setw; using std::left;

typedef ranlux3_01 eng_t;
typedef gamma_distribution <> dist_t;
typedef variate_generator <eng_t&, dist_t > gen_t;

const int nvals = 10;

int main()
  { // demonstrate variate generator
  eng_t eng;
  dist_t dist;
  gen_t gen(eng, dist);
  array <gen_t::result_type,nvals> res0, res1;
  for (int i = 0; i < nvals; ++i)
    res0[i] = dist(eng);

  for (int i = 0; i < nvals ; ++i)
    res1[i] = gen ();

  cout << "Part 1\n" << left;
  for (int i = 0; i < nvals; ++i)
    cout << setw(12) << res0[i] << ' '
      << setw(12) << res1[i] << '\n';

  // restart
  eng.seed();
  dist.reset();
  gen.distribution().reset();
  for (int i = 0; i < nvals; ++i)
    res0[i] = dist(eng);

  eng.seed();
  gen.distribution().reset();
  for (int i = 0; i < nvals; ++i)
    res1[i] = gen();

  cout << "\nPart2\n";
  for (int i = 0; i < nvals ; ++i)
    cout << setw(12) << res0[i] << ' '
      << setw(12) << res1[i] << '\n';
  return 0;
  }

In Part 1 of this example, note that the pairs of values are not the same. That's because the engine argument to the variate_generator instantiation is a reference to eng_t instead of simply eng_t. As a result, the gen object holds a reference to eng instead of a copy of it. The calls to dist(eng) change the state of eng, and the subsequent calls to gen() use its new state. To get the same sequence as we got with dist(eng), we have to reseed eng, as shown in Part 2.

The two preceding examples have simply encapsulated an engine and a distribution. The code to generate sequences of random numbers is slightly simpler, because you don't have to pass an engine to the distribution; the variate_generator template takes care of that.

In addition, when you use variate_generator, you don't have to match the engine's result_type to the distribution's input_type, and, when the distribution takes a floating-point type, you aren't restricted to engines that generate values in the closed range [0.0, 1.0].

Example 13.6. Matching Type and Range with variate_generator (random/varmatch.cpp)

#include <random>
#include <iostream>
using std::tr1::variate_generator;
using std::tr1::mt19937 ;
using std::cout;

struct identity
  { // trivial floating-point distribution
  typedef double input_type;
  typedef double result_type;
  template <class Engine>
    double operator()(Engine & eng)
      { // return value from eng()
      return eng ();
      }
  };

typedef mt19937 eng_t;
typedef identity dist_t ;
typedef variate_generator <eng_t , dist_t > gen_t;

const int nvals = 10;

int main()
  { // demonstrate type matching and range adjustment
  eng_t eng;
  dist_t dist;
  gen_t gen(eng, dist);
  for (int i = 0; i < nvals; ++i)
    cout << gen() << '\n';
  return 0;
  }


Further Reading

  • The Art of Computer Programming [Knu98a, 1193] is, as usual, an outstanding reference.

  • Numerical Recipes in C [PTVF92] has implementations of several engines and distributions.

  • e-Handbook of Statistical Methods, section 1.3.6.6" [NIS] has information on many statistical distributions. See www.itl.nist.gov/div898/handbook/eda/section3/eda366.htm.


Exercises

Exercise 1

  1. Create an engine object that applies the recurrence relation xi =(2.xi-1 + 1) mod 6. Seed the object with the value 0, and generate a sequence of several thousand elements, counting the number of times each value occurs. Try it two more times, with seeds of 1 and 2. Would you bet your life on this roll?

  2. Does picking a multiplier and modulus that are relatively prime improve this engine? Create an engine object that applies the recurrence relation xi =(5 xi-1 + 1) mod 6, and repeat the previous test.

  3. Does picking a modulus that is a prime number improve this engine? Create an engine object that applies the recurrence relation xi =(2.xi-1 + 1) mod 7, and repeat the previous test.

Exercise 2

Write a typedef for a subtract_with_carry instantiation with a modulus of 6, a short lag of 4, and a long lag of 7. It should return values of type int.[22]

[22] These lags are far too small to generate good values, and the seed values that we use later are not particularly good, but they have the advantage of being easy to describe and easy to code. When you use random number engines in real programs, neither of these factors is important.

  1. Create an object of this type with the default constructor, and examine the first few values that it generates.

  2. Call seed() on the object in the previous part, and verify that the first few values generated by the engine are the same as before.

  3. Write a function that takes no arguments and returns values of type unsigned int. Successive calls to this function should return the values 0, 1, 2, and so on. Use this function to seed the engine, and examine the first few values that the engine generates.

  4. Write a class template that takes one type argument named InIt. The class should store two values of that type, named first and last, and should have a constructor that takes two arguments of that type and copies them to first and last. The class should also have an operator() that returns values of type std::iterator_-traits<InIt>::value_type, [23] with the following properties.

    [23] By now, you've probably guessed that InIt represents an input iterator.

    1. If first == last, it should throw an exception of type std ::length_error.

    2. Otherwise, it should return *first++.

    Using std::vector, create an object named seeds that holds seven unsigned int values such that seeds[i] == i for i ranging from 0 to 6. Use your class template to create an object that holds begin and end iterators to this vector object. Use that object to seed the engine, and verify that the first few values generated by the engine are the same as before.

Exercise 3

Write a program that uses floating-point values from one of the predefined engines to generate values in the closed range [0, 1]. Generate several thousand values, and show the frequency of each of the generated values.

Exercise 4

Write a program that (a) creates an object whose type is one of the predefined engines that generates integer values and (b) creates an object of type bernoulli_distribution that returns TRue with probability one-half. Use the engine object as the source of random values for the generator to generate several thousand values, and show the frequency of each of the resulting values.

Exercise 5

Write a program that (a) creates an object whose type is one of the predefined engines that generates integer values and (b) creates an object whose type is an instantiation of uniform_int that generates values in the closed range [0, 1]. Use the engine object as the source of random values for the generator to generate several thousand sets of four values and adds the four values in each set together. Show the frequency of each of the resulting values.

Exercise 6

Write a program that (a) creates an object whose type is one of the predefined engines that generates integer values and (b) creates an object whose type is an instantiation of binomial_distribution that generates values in the closed range [0, 4], with a probability of success of one-half. Combine the engine and the generator, using variate_generator. Generate several thousand values, and show the frequency of each of the resulting values.


Part VI: Regular Expressions

    Chapter 14. The <regex> Header

    Chapter 15. Regular Expression Grammars

    Chapter 16. Regular Expression Objects

    Chapter 17. Searching

    Chapter 18. Search Results

    Chapter 19. Repetitive Searches

    Chapter 20. Formatting and Text Replacement

    Chapter 21. Customizing Regular Expressions


Chapter 14. The <regex> Header

Great blunders are often made, like large ropes, of a multitude of fibers.

Les Misérables
VICTOR HUGO

Powerful software facilities, too, are often made of a multitude of fibers. The <regex> header offers a somewhat daunting set of class templates and function templates for searches using regular expressions. Don't let the size of the header deter you, though; you need to understand only a few basic ideas to use regular expressions effectively. You need to know how to write a regular expression (Chapter 15), how to create an object that holds a regular expression (Chapter 16), how to use a regular expression object to search for matches in a target string (Chapter 17), and how to hold the results of a search (Chapter 18). For more sophisticated applications you can create iterator objects that perform multiple sequential searches (Chapter 19), suitable for use as input sequences to STL algorithms, and you can scan input text, replacing portions selected by a regular expression (Chapter 20). Finally, if you really need to, you can customize some aspects of the regular expression engine (Chapter 21). We look at each of these subjects in a bit more detail in the rest of this chapter and in far more detail in subsequent chapters.

A regular expression is a sequence of characters that can match one or more target sequences of characters according to the rules of a regular expression grammar. For example, the regular expression "sequence[^s]" matches the text "sequence" earlier in this sentence but not the text "sequences." The rules that determine what is and isn't a valid regular expression and what a valid regular expression means are called the regular expression grammar. The grammars supported by the TR1 library are discussed in Chapter 15.

When writing regular expressions, it's important to keep in mind that a backslash character has a special meaning both in regular expression grammars and in C++. When you write a regular expression as a string literal in code, the compiler gets the first shot at any backslashes and will treat them as escape characters. If you need to have a backslash in the regular expression itself, you must use two backslashes in the string literal. For example, the regular expression "\.a" is the character '\' followed by the character '.' followed by the character 'a'. In code, however, a string literal representing that same regular expression has two backslashes.

std::string str("\\.a");     // str holds the character sequence '\'
'.' 'a'

Once you know how to write a regular expression that correctly describes the text pattern you want to search for, you need to create an object that encapsulates that pattern. The class template basic_regex does this for more or less arbitrary types of characters. You'll almost always be providing regular expressions as sequences of char or wchar_t, for which you'll use the specializations of basic_regex named regex and wregex, respectively. Objects of these types are constructed from a text sequence that defines a regular expression:

std ::tr1 :: regex rgx(str );    // rgx holds the regular expression "\.a"

When you search for text that matches the pattern defined by a regular expression, you're often interested in more than simply whether a match was found. You usually want to know where the match was in the target sequence and, sometimes, where some matching subsequences occurred. These results are reported through the class templates sub_match and match_results or, more commonly, through their specializations for use with particular kinds of target sequences. In the following code snippet, cmatch can hold the results of a search through an array of char:

std ::tr1 :: cmatch match ;    // match will receive search results

Of course, the reason for using a regular expression in the first place is to search for text that matches it. Three function templates search for matching text. The function template regex_match checks whether a target sequence exactly matches the regular expression. The function template regex_search looks for the first matching subsequence. The function template regex_replace looks for matches and replaces them with new text. These functions all take a regular expression object that defines the pattern to search for and a target sequence that will be searched. The various overloads of the function templates regex_match and regex_search all return a Boolean value that indicates whether a match was found. Some of the overloads of these function templates also take a match_results object for more detailed results:

if ( std ::tr1 :: regex_search (" aba .a", match, rgx ))
   std :: cout << " match found after "
      << match .prefix () << '\n';

In the preceding code snippet, regex_search looks for the first position in the text "aba.a" that matches the regular expression. That match consists of the fourth and fifth characters, so the code snippet will display "match found after aba".

Here is the complete program that these code snippets were taken from.

Example 14.1. Regular Expression Overview (regexhdr/overview.cpp)

# include  < regex >
# include  < iostream >
# include  < string >
using std :: tr1 :: regex ;
using std :: tr1 :: cmatch ; using std :: tr1 :: regex_search ;
using std :: cout ; using std :: string ;

int main ()
     {
     string str (" \\. a");
     regex  rgx ( str);
     cmatch match ;
     if    ( std :: tr1 :: regex_search (" aba .a",  match, rgx))
      std :: cout << " match found after           "
         << match . prefix () <<   ' \n ' ;
     return 0;
     }

Sometimes, your program needs to split its input text into chunks according to a set of rules that can be defined by a regular expression. Two forms of regular expression iterators do this. You can call an STL algorithm with such an iterator object, and the algorithm will see the individual chunks. In the example that follows, all the code before main is infrastructure. The regex object word_sep holds a regular expression that matches any sequence of text consisting of one or more separator characters, where a separator character is a space, a comma, a period, a horizontal tab, a newline, a semicolon, or a colon. The object words, of type sregex_token_iterator, uses word_sep to separate the input sequence [text.begin(), text.end()) into tokens separated by subsequences that match the regular expression. Thus, each token is a word from the input text. The map object word_count counts the number of times each word appears in the text. The while loop loops through the words, as determined by words, and increments the count for each word it encounters. The call to copy shows the result.

Example 14.2. Regular Expression Iteration (regexhdr/regexiter.cpp)

#include <regex>
#include <algorithm>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <map>
#include <string>
using std::tr1::regex;
using std::tr1::sregex_token_iterator;
using std::map;
using std::cout; using std::basic_ostream;
using std::setw; using std::ostream_iterator;
using std::string; using std::copy;

string text =
"The quality of mercy is not strain'd,\n"
"It droppeth as the gentle rain from heaven\n"
"Upon the place beneath: it is twice bless'd;\n"
"It blesseth him that gives and him that takes:\n"
"'Tis mightiest in the mightiest; it becomes\n"
"The throned monarch better than his crown;\n"
"His sceptre shows the force of temporal power,\n"
"The attribute to awe and majesty,\n"
"Wherein doth sit the dread and fear of kings\n";
// William Shakespeare, The Merchant of Venice

typedef map<string, int> counter;
typedef counter::value_type pairs;

namespace std { // add inserter to namespace std
template <class Elem, class Alloc>
basic_ostream<Elem, Alloc>& operator<<(
  basic_ostream<Elem, Alloc>& out, const pairs& val)
  { // insert pair<string, int> into stream
  return out << setw(10) << val.first
    << ": " << val.second;
  }
}

int main ()
  {  // count occurrences of each word
  regex word_sep ("[ ,.\\t\\n;:]+");
  sregex_token_iterator words(
    text.begin(), text.end(), word_sep, -1);
  sregex_token_iterator end;
  map<string, int> word_count;
  while (words != end)
    ++word_count[*words++];
  copy(word_count.begin(), word_count.end(),
    ostream_iterator<pairs>(cout, "\n"));
  return 0;
  }

Finally, it's possible to customize the regular expression grammars in limited ways. Each basic_regex object has a traits object that it uses to determine whether a particular character has a special meaning and what that meaning is, whether two characters should be treated as equivalent, and so on. This customization is discussed in Chapter 21.


Further Reading

  • Mastering Regular Expressions [Fri02] is a very good discussion, with lots of examples, of how to use regular expressions and of the intricacies of their grammars.

  • Ecma-262, ECMAScript Language Specification [Ecm03] is the formal reference that the TR1 library's ECMAScript grammar is based on.

  • Portable Operating System Interface (POSIX) [Int03b, Int03c] is the formal reference that the TR1 library's bre, ere, grep, egrep, and awk grammars are based on.


Chapter 15. Regular Expression Grammars

When a thought takes ones breath away, a lesson on grammar seems an impertinence.

Preface to Emily Dickinson's Poems, First Series
THOMAS WENTWORTH HIGGINSON

A regular expression grammar defines the rules for writing and interpreting a regular expression. The TR1 library supports six grammars. These grammars have a lot in common, so many regular expressions match the same set of target sequences, regardless of which grammar is being used. However, the grammars also have significant differences, so some things that are valid under one grammar are illegal under another; worse, some things that mean one thing under one grammar mean something different under another. It's important to know which grammar you're using, so that you don't accidentally write a regular expression that does something other than what you intended it to do.

The six grammars supported by the TR1 library are

  1. BRE: Basic Regular Expressions, defined in Part 1 of the POSIX Standard ([Int03b])

  2. ERE: Extended Regular Expressions, defined in Part 1 of the POSIX Standard ([Int03b])

  3. ECMAScript: ECMAScript Regular Expressions, based on the ECMAScript Language Specification ([Ecm03])[1]

    [1] The ECMAScript grammar in the TR1 library is a superset of the ECMAScript language.

  4. awk: regular expressions as used in the awk utility, defined in Part 3 of the POSIX Standard ([Int03c])

  5. grep: regular expressions as used in the grep utility, defined in Part 3 of the POSIX Standard ([Int03c])

  6. egrep: regular expressions as used in the grep utility with the -E option, defined in Part 3 of the POSIX Standard ([Int03c])

If you don't ask for a particular grammar, you'll get ECMAScript.

Because they have so many similarities, we look at all six grammars together. Some constructs aren't available in some grammars. Discussions of those constructs list the grammars that support them. Some constructs use different syntax in different grammars. Discussions of those grammars point out those syntactic differences.

This grammar discussion has three parts. The first (Section 15.1) gives an overview of the structure of a regular expression. You should read this section carefully and be sure that you understand it. The second (Section 15.2) is a table, showing which constructs are available in each of the grammars. You should look through the entries for ECMAScript, since that's the default, to be sure that you know what can be done with it. The third (Section 15.3) gives the details. You'll probably refer back to it fairly often when you get confused.

In this chapter, names in SMALL CAPITALS refer to the definitions in Section 15.3.

This discussion of regular expressions is complete but terse. See [Fri02] for lengthier discussions and lots of examples.


Section 15.1. Structure of Regular Expressions

15.1. Structure of Regular Expressions

15.1.1. Element

An element can be any of the following:

  • An ORDINARY CHARACTER, which matches the same character in the target sequence.

  • A WILDCARD CHARACTER, '.', which matches any character in the target sequence except a newline.

  • A BRACKET EXPRESSION, of the form "[expr]", which matches a single character or a COLLATING ELEMENT in the target sequence that is also in the set defined by the expression expr, oroftheform "[^expr]", which matches a single character or a collation element in the target sequence that is not in the set defined by the expression expr. In either case, the expression expr can consist of any combination of any number of each of the following:

    - An INDIVIDUAL CHARACTER, which adds that character to the set defined by expr

    - A CHARACTER RANGE, of the form "ch1-ch2", which adds all the characters represented by values in the closed range [ch1, ch2] to the set defined by expr

    - A CHARACTER CLASS, of the form "[:name:]", which adds all the characters in the named class to the set defined by expr

    - A COLLATING SYMBOL, of the form "[.elt.]", which adds the collation element elt to the set defined by expr

    - An EQUIVALENCE CLASS, of the form "[=elt=]", which adds the collating elements that are equivalent to elt to the set defined by expr

  • An ANCHOR, either '^' or '$', which matches the beginning or the end of the target sequence, respectively.

  • A CAPTURE GROUP, of the form "(subexpression)" (written as "\(subexpression\)" in BRE and grep), which matches the sequence of characters in the target sequence matched by the subexpression between the delimiters.

  • An IDENTITY ESCAPE, of the form "\k", which matches the character k in the target sequence.

For example:

  • "a" matches the target sequence "a" but does not match any of the target sequences "B", "b", or "c".

  • "." matches all the target sequences "a", "B", "b", and "c".

  • "[b-z]" matches the target sequences "b" and "c" but does not match the target sequence "a" or the target sequence "B".

  • "[[:lower:]]" matches the target sequences "a", "b", and "c" but does not match the target sequence "B".

  • "(a)" matches the target sequence "a" and associates capture group 1 with the subsequence "a" but does not match any of the target sequences "B", "b", or "c".

In ECMAScript, BRE, and grep, an element can also be

  • A BACK REFERENCE, of the form "\d", as well as "\dd" in ECMA-Script, which matches a sequence of characters in the target sequence that is the same as the sequence of characters matched by the Nth CAPTURE GROUP, where N is the value represented by the decimal digit d or by the decimal digits dd.

For example:

  • "(a)\1" matches the target sequence "aa" because the first, and only, capture group matches the initial sequence "a", and the back reference \1 then matches the final sequence "a".

In ECMAScript, an element can also be any of the following:

  • A NONCAPTURE GROUP, of the form "(?:subexpression)"; the group matches the sequence of characters in the target sequence matched by the subexpression between the delimiters.

  • A limited FILE FORMAT ESCAPE, of the form "\f", "\n", "\r", "\t", or "\v"; these match a form feed, newline, carriage return, horizontal tab, and vertical tab, respectively, in the target sequence.

  • A POSITIVE ASSERT, of the form "(?=subexpression)", which matches the sequence of characters in the target sequence matched by the subexpression between the delimiters but does not change the match position in the target sequence.

  • A NEGATIVE ASSERT, of the form "(?!subexpression)", which matches any sequence of characters in the target sequence that does not match the subexpression between the delimiters but does not change the match position in the target sequence.

  • A HEXADECIMAL ESCAPE SEQUENCE, of the form "\x hh "; the sequence matches a character in the target sequence whose representation is the value represented by the two hexadecimal digits hh.

  • A UNICODE ESCAPE SEQUENCE, of the form "\u hhhh ", which matches a character in the target sequence whose representation is the value represented by the four hexadecimal digits hhhh.

  • A CONTROL ESCAPE SEQUENCE, of the form "\c k ", which matches the control character named by the character k.

  • A WORD BOUNDARY ASSERT, of the form "\b", which matches if the current position in the target sequence is immediately after a word boundary.

  • A NEGATIVE WORD BOUNDARY ASSERT, of the form "\B"; the assert matches if the current position in the target sequence is not immediately after a word boundary.

  • A DSW CHARACTER ESCAPE, of the form "\d", "\D", "\s", "\S", "\w", "\W", which provides a short name for a character class.

For example:

  • "(?:a)" matches the target sequence "a".

  • "(?:a)\1" is invalid, because there is no capture group 1.

  • "(?=a)a" matches the target sequence "a". The assert matches the initial sequence "a" in the target sequence, and the final "a" in the regular expression matches the initial sequence "a" in the target sequence.

  • "(?!a)a" does not match the target sequence "a"; nor does it match any other target sequence.

  • "a\b." matches the target sequence "a!" but does not match the target sequence "ab".

  • "a\B." matches the target sequence "ab" but does not match the target sequence "a!".

In awk, an element can also be one of the following:

  • A FILE FORMAT ESCAPE, of the form "\\", "\a", "\b", "\f", "\n", "\r", "\t", or "\v"; these match a backslash, alert, backspace, form feed, newline, carriage return, horizontal tab, and vertical tab, respectively, in the target sequence.

  • An OCTAL ESCAPE SEQUENCE, of the form "\ooo", which matches a character in the target sequence whose representation is the value represented by the one, two, or three octal digits ooo.

15.1.2. Repetition

Any element other than a POSITIVE ASSERT, a NEGATIVE ASSERT, or an ANCHOR can be followed by a repetition count. The most general form of a repetition count is "{min, max}" (written as "\{min, max\}" in BRE and grep). An element followed by this form of repetition count matches at least min and no more than max successive occurrences of sequences that match the element.

For example:

  • "a{2, 3}" matches the target sequence "aa" and the target sequence "aaa" but not the target sequence "a" or the target sequence "aaaa".

A repetition count can also take one of the following forms:

  • "{min}" (written as "\{min\}" in BRE and grep), which is equivalent to "{min, min}"

  • "{min,}" (written as "\{min,\}" in BRE and grep), which is equivalent to "{min, unbounded}"

  • "*", which is equivalent to "{0, unbounded}"

For example:

  • "a{2}" matches the target sequence "aa" but not the target sequence "a" or "aaa".

  • "a{2,}" matches the target sequence "aa", the target sequence "aaa", and so on, but does not match the target sequence "a".

  • "a*" matches the target sequence "", the target sequence "a", the target sequence "aa", and so on.

For all grammars except BRE and grep, a repetition count can also take one of the following forms:

  • "?", which is equivalent to "{0, 1}"

  • "+", which is equivalent to "{1, unbounded}"

For example:

  • "a?" matches the target sequence "" and the target sequence "a" but not the target sequence "aa".

  • "a+" matches the target sequence "a", the target sequence "aa", and so on, but not the target sequence "".

All the previous repetition counts apply a greedy repetition, which matches as many characters as possible in the target sequence. In ECMAScript, all the forms of repetition count can be followed by the character '?' to specify a non-greedy repetition. A nongreedy repetition matches as few characters as possible in the target sequence.

For example:

  • "(a+)a*" matches the target sequence "aa" and associates capture group 1 with the entire target sequence because the element inside the capture group ("a+") uses a greedy match.

  • "(a+?)a*" matches the target sequence "aa" and associates capture group 1 with the initial subsequence "a" because the element inside the capture group ("a+?") uses a nongreedy match.

15.1.3. Concatenation

Regular expression elements, with or without repetition counts, can be concatenated to form longer regular expressions. Such a concatenated regular expression matches a target sequence that is a concatenation of sequences matched by the individual elements.

For example:

  • "a{2, 3}c" matches the target sequence "aac" and the target sequence "aaac" but does not match the target sequence "ac" or the target sequence "aaaac".

  • "ab{2, 3}c" matches the target sequence "abbc" and the target sequence "abbbc" but does not match the target sequence "ababc".

  • "(ab){2, 3}c" matches the target sequence "ababc" and the target sequence "abababc" but does not match the target sequence "abbc".

15.1.4. Alternation

For all the regular expression grammars except BRE and grep, a concatenated regular expression can be followed by the character '|' and another concatenated regular expression, which can be followed by another '|' and another concatenated regular expression, and so on. Such an expression matches any target sequence that matches one or more of the concatenated regular expressions.

For example:

  • "ab|cd" matches the target sequence "ab" and the target sequence "cd" but does not match the target sequence "abd" or the target sequence "acd".

In grep and egrep, a newline character ('\n') can be used to separate alternations.[2]

[2] The UNIX utilities grep and egrep can take a file as the source of the regular expression that they try to match. In that case, each line in the file is a separate concatenated regular expression.

When a match succeeds, if more than one of the concatenated regular expressions matches in an alternation could match part of the target sequence, ECMAScript chooses the first of the concatenated regular expressions that matches the target sequence as the match; the other regular expression grammars choose the one that results in the longest match.

For example:

  • "(a|ab).*" matches the target sequence "abc". In ECMAScript, the capture group is associated with the initial sequence "a" because it matched the first element in the alternation. Under the other grammars, the capture group is associated with the initial sequence "ab" because it gave the longest match in the alternation.

15.1.5. Subexpression

A subexpression is a concatenated regular expression in BRE and grep and an alternation in the other regular expression grammars. This is where the specification for regular expressions becomes recursive. In particular, as we saw earlier, a capture group can hold a subexpression. This makes it possible to nest subexpressions to create rather complicatedand potentially unreadableregular expressions.

For example:

  • "(a(.*)d)" matches the target sequence "abcd", associates capture group 1 with the text "abcd", and associates capture group 2 with the text "bc".[3]

    [3] Capture group 1 begins with the first '(', and capture group 2 begins with the second.

  • "(a(.*)d)\1" matches the target sequence "abcdabcd". It associates capture group 1 with the initial text "abcd", and the back reference matches the corresponding text at the end of the target text.

  • "(a(.*)d)\2" matches the target sequence "abcdbc". It associates capture group 2 with the first occurrence of "bc", and the back reference matches the corresponding text at the end of the target text.


Section 15.2. Grammar Features

15.2. Grammar Features

Table 15.1 presents the full list of regular expression grammar features and the grammars that support them.

Table 15.1. Grammar Features

Element

ECMA-Script

BRE

ERE

grep

egrep

awk

ALTERNATION, '|'

+

+

+

+

ALTERNATION, '\n'

+

+

ANCHOR

+

+

+

+

+

+

BACK REFERENCE

+

+

+

BRACKET EXPRESSION

+

+

+

+

+

+

CAPTURE GROUP, "()"

+

+

+

+

CAPTURE GROUP, "\(\)"

+

+

CONTROL ESCAPE SEQUENCE

+

DSW CHARACTER ESCAPE

+

FILE FORMAT ESCAPE

+

+

HEXADECIMAL ESCAPE SEQUENCE

+

IDENTITY ESCAPE

+

+

+

+

+

+

NEGATIVE ASSERT

+

NEGATIVE WORD BOUNDARY ASSERT

+

NONCAPTURE GROUP

+

OCTAL ESCAPE SEQUENCE

+

ORDINARY CHARACTER

+

+

+

+

+

+

POSITIVE ASSERT

+

REPETITION, "{}"

+

+

+

+

REPETITION, "\{\}"

+

+

REPETITION, "*"

+

+

+

+

+

+

REPETITION, '?' and '+'

+

+

+

+

UNICODE ESCAPE SEQUENCE

+

WILDCARD CHARACTER

+

+

+

+

+

+

WORD BOUNDARY ASSERT

+


Section 15.3. Regular Expression Details

15.3. Regular Expression Details

15.3.1. Anchor

An anchor matches a position in the target string and not a character. A '^' matches the beginning of the target sequence, and a '$' matches the end of the target sequence.

15.3.2. Back Reference

A back reference is a backslash followed by a decimal value N and matches the contents of the Nth CAPTURE GROUP. The value of N must not be greater than the number of complete capture groups that precede the back reference. In BRE and grep, the value of N is never greater than 9, even if the regular expression has more than nine capture groups. In ECMAScript, the value of N is never greater than 99. Back references are not supported in ERE, egrep, and awk. For example:

  • "((a+)(b+))(c+))\3" matches the target sequence "aabbcbbb". The back reference "\3" matches the text in the third capture group, that is, the "(b+)". The regular expression does not match the target sequence "aabbbcbb".

  • "(a)\2" is not valid.

  • "(b(((((((((a))))))))))\10" matches the target sequence "baa" in ECMAScript; the back reference is "\10" and it matches the tenth capture group (i.e., the innermost one). In BRE, in the analogous regular expression

    "\(b \(\(\(\(\(\(\(\(\( a \)\)\)\)\)\)\)\)\)\)\10"

    the back reference is "\1". It matches the first capture groupthe one beginning with "\(b" and ending with the final "\)" preceding the back referenceand the final '0' matches the ordinary character '0'.

15.3.3. Bracket Expression

A bracket expression defines a set of characters and COLLATING ELEMENTS. If the bracket expression begins with the character '^', the match succeeds if none of the elements in the set matches the current character in the target sequence. Otherwise, the match succeeds if any of the elements in the set matches the current character in the target sequence.

The set of characters can be defined by listing any combination of INDIVIDUAL CHARACTERS, CHARACTER RANGES, CHARACTER CLASSES, COLLATING SYMBOLS, and EQUIVALENCE CLASSES.

15.3.4. Capture Group

A capture group marks its contents as a single unit in the regular expression grammar and associates the capture group with the subsequence of the target sequence that matches its contents. Each capture group has a number, determined by counting the left delimiters ('(' or "\(") marking capture groups up to and including the left parenthesis marking the current capture group. For example:

  • "ab+" matches the target sequence "abb" but not the target sequence "abab".

  • "(ab)+" does not match the target sequence "abb" but matches the target sequence "abab".

  • "((a+)(b+))(c+))" matches the target sequence "aabbbc" and associates capture group 1 with the subsequence "aabbb", capture group 2 with the subsequence "aa", capture group 3 with the subsequence "bbb", and capture group 4 with the subsequence "c".

15.3.5. Character Class

A character class in a bracket expression adds all the characters in the named class to the character set defined by the bracket expression. To add the contents of a character class to a bracket expression, use "[:" followed by the name of the character class followed by ":]". Internally, the name of a character class is recognized by calling the member functions lookup_classname and isctype on the regular expression object's traits object. The default traits class supports the following class names:

  • "alnum": lowercase letters, uppercase letters, and digits

  • "alpha": lowercase letters and uppercase letters

  • "blank": space or tab

  • "cntrl": the FILE FORMAT ESCAPE characters

  • "digit": digits

  • "graph": lowercase letters, uppercase letters, digits, and punctuation

  • "lower": lowercase letters

  • "print": lowercase letters, uppercase letters, digits, punctuation, and space

  • "punct": punctuation

  • "space": space

  • "upper": uppercase letters

  • "xdigit": digits, 'a', 'b', 'c', 'd', 'e', 'f', 'A', 'B', 'C', 'D', 'E', 'F'

  • "d": same as "digit"

  • "s": same as "space"

  • "w": same as "alnum"

15.3.6. Character Range

A character range in a bracket expression adds all the characters in the range to the character set defined by the bracket expression. To create a character range put the character '-' between the first and last characters in the range. This puts into the set all the characters whose representation has a numeric value that is greater than or equal to the numeric value of the representation of the first character and less than or equal to the numeric value of the representation of the last character. Note that the contents and validity of this set of added characters depend on the platform-specific representation of characters. If the character '-' occurs at the beginning or the end of a bracket expression or as the first or last character of a character range it represents itself. For example:

  • "[0-7]" represents the characters in the set { '0', '1', '2', '3', '4', '5', '6', '7' }. It matches the target sequences "0", "1", and so on, but not the target sequence "a".

  • "[h-k]" represents the characters in the set { 'h', 'i', 'j', 'k' } on systems that use the ASCII character encoding. It matches the target sequences "h", "i", and so on, but not the target sequences "\x8A" or "0".

  • "[h-k]" represents the characters in the set { 'h', 'i', '\x8A', '\x8B', '\x8C', '\x8D', '\x8E', '\x8F', '\x90', 'j', 'k' } on systems that use the EBCDIC character encoding; 'h' is encoded as 0x88, and 'k' is encoded as 0x92. It matches the target sequences "h", "i", "\x8A", and so on, but not "0".

  • "[-0-24]" represents the set of characters { '-', '0', '1', '2', '4' }.

  • "[0-2-]" represents the set of characters { '0', '1', '2', '-' }.

  • "[+--]" represents the set of characters { '+', ', ', '-' } on systems that use ASCII.

You can pass a flag that changes this to the constructor of a regular expression object. When you select locale-sensitive ranges, the characters are determined by the collation rules for the regular expression's locale. Characters that collate after the first character in the definition of the range and before the last character in the definition of the range are in the set, as well as the two end characters.

15.3.7. Collating Element

A collating element is a multicharacter sequence that is treated as a single character.

15.3.8. Collating Symbol

A collating symbol in a bracket expression adds a COLLATING ELEMENT to the set defined by the bracket expression. To add a collating symbol to the set defined by a bracket expression, use "[." followed by the collating element followed by ".]".

15.3.9. Control Escape Sequence

A control escape sequence is a backslash followed by the letter 'c' followed by one of the letters 'a' tHRough 'z' or 'A' tHRough 'Z'. The escape sequence matches the ASCII control character named by that letter. For example:

  • "\ci" matches the target sequence "\x09" because <ctrl-i> has the value 0x09.

15.3.10. DSW Character Escape

A dsw character escape is a short name for a bracket expression containing a single character class. In Table 15.2, the second column shows the meaning of each of the dsw character escapes, and the third column shows the meaning with the default traits class.

Table 15.2. DSW Character Escapes

Escape Sequence

Equivalent Named Class

Default Implementation

"\d"

"[[:d:]]"

"[[:digit:]]"

"\D"

"[^[:d:]]"

"[^[:digit:]]"

"\s"

"[[:s:]]"

"[[:space:]]"

"\S"

"[^[:s:]]"

"[^[:space:]]"

"\w"

"[[:w:]]"

"[a-zA-Z0-9_]"[*]

"\W"

"[^[:w:]]"

"[^a-zA-Z0-9_]"[*]

[*] ASCII character set

15.3.11. Equivalence Class

An equivalence class in a bracket expression adds all the characters and COLLATING ELEMENTS that are equivalent to the collating element in the equivalence class definition to the set defined by the bracket expression. To add the characters in an equivalence class to the set defined by a bracket expression, use "[=" followed by a collating element followed by "=]".

15.3.12. File Format Escape

A file format escape represents the usual C-language character escapes"\\", "\a", "\b", "\f", "\n", "\r", "\t", and "\v"with their usual meanings, namely, backslash, alert, backspace, form feed, newline, carriage return, horizontal tab, and vertical tab, respectively. In ECMAScript, "\a" and "\b" are not allowed. (Although "\\" is allowed, technically it's an identity escape, not a file format escape.)

15.3.13. Hexadecimal Escape Sequence

A hexadecimal escape sequence is a backslash followed by the letter 'x' followed by two hexadecimal digits (0-9a-fA-F). This sequence matches a character in the target sequence with the value specified by the two digits. For example:

  • "\x41" matches the target sequence "A" when the ASCII character encoding is used.

15.3.14. Identity Escape

An identity escape is a backslash followed by a single character. The escape matches that character and is needed when the character has a special meaning in the regular expression grammar; using the identity escape removes the special meaning. For example:

  • "a*" matches the target sequence "aaa" but does not match the target sequence "a*".

  • "a\*" does not match the target sequence "aaa" but does match the target sequence "a*".

The set of characters allowed in an identity escape depends on the regular expression grammar.

  • BRE and grep

       . [ \ * ^ $

  • ERE and egrep

       . [ \ () * + ? { | ^ $

  • awk

       . [ \ () * + ? { | ^ $ " /

  • ECMAScript: all characters except those that can be part of an identifier: roughly speaking, letters, digits, '$', '_', and Unicode escape sequences. For full details, see the ECMAScript Language Specification ([Ecm03]).

15.3.15. Individual Character

An individual character in a bracket expression adds that character to the character set defined by the bracket expression. A '^' anywhere other than at the beginning of a bracket expression represents itself. For example:

  • "[abc]" matches the target sequences "a", "b", and "c" but not "d".

  • "[^abc]" matches the target sequence "d" but not "a", "b", and "c".

  • "[a^bc]" matches the target sequences "a", "b", "c", and "^" but not "d".

In all the regular expression grammars except ECMAScript, if a ']' is the first character following the opening '[' in a bracket expression or the first character following an initial '^' in a bracket expression, it represents itself. For example:

  • "[]a" is invalid because there is no ']' to end the bracket expression.

  • "[]abc]" matches the target sequences "]", "a", "b", and "c" but not "d".

  • "[^]abc]" matches the target sequence "d" but not "]", "a", "b", and "c".

In ECMAScript, use "\]" to represent the character ']' in a bracket expression.

  • "[]a" does not match any target sequence, because the bracket expression is empty.

  • "[\]abc]" matches the target sequences "]", "a", "b", and "c" but not "d".

15.3.16. Negative Assert

A negative assert matches anything but its contents; it does not consume any characters in the target sequence. For example:

  • "(?!aa)(a*)" matches the target sequence "a" and associates capture group 1 with the subsequence "a" but it does not match the target sequence "aa" or the target sequence "aaa".

15.3.17. Negative Word Boundary Assert

A negative word boundary assert matches if the current position in the target sequence is not immediately after a word boundary. See WORD BOUNDARY ASSERT.

15.3.18. Noncapture Group

A noncapture group marks its contents as a single unit in the regular expression grammar but does not associate any group number with the matching target sequence. For example:

  • "(a)(?:b)(c)" matches the target text "abc" and associates capture group 1 with the subsequence "a" and capture group 2 with the subsequence "c".

15.3.19. Octal Escape Sequence

An octal escape sequence is a backslash followed by one, two, or three octal digits (0-7). This sequence matches a character in the target sequence whose representation has the value specified by those digits. If all the digits are '0', the sequence is invalid. For example:

  • "\101" matches the target sequence "A" when the ASCII character encoding is used.

15.3.20. Ordinary Character

An ordinary character is any valid character that doesn't have a special meaning in the current grammar.

  • In ECMAScript, the characters that have special meanings are

         ^$  . * + ? ()  [ ]     |

  • In BRE and grep, the characters that have special meanings are

         . [

    '*' has a special meaning in all cases except when it is the first character in a regular expression, the first character following an initial '^' in a regular expression, the first character in a capture group, or the first character following an initial '^' in a capture group.

  • In ERE, egrep, and awk, the characters that have special meanings are

         . [ \ ( * + ? { |

    In addition, the following characters have special meanings when used in a particular context:

    ')' has a special meaning when it matches a preceding '('.

    '^' has a special meaning when it is the first character of a regular expression.

    '$' has a special meaning when it is the last character of a regular expression.

An ordinary character matches the same character in the target sequence. By default, this means that the match succeeds if the two characters are represented by the same value. When you select case-insensitive matching, character equality is determined by calling the member function translate_-nocase on the regular expression object's traits object. When you select a locale-sensitive match, character equality is determined by calling the member function translate on the regular expression object's traits object.

15.3.21. Positive Assert

A positive assert matches its contents but does not consume any characters in the target sequence. For example:

  • "(aa)(a*)" matches the target sequence "aaaa" and associates capture group 1 with the subsequence "aa" at the beginning of the target sequence and capture group 2 with the subsequence "aa" at the end of the target sequence.

  • "(?=aa)(a*)" matches the target sequence "aaaa" and associates capture group 1 with the subsequence "aaaa".

  • "(?=aa)(a*)|(a*)" matches the target sequence "a" and associates capture group 1 with an empty sequencebecause the positive assert failedand capture group 2 with the subsequence "a". The regular expression also matches the target sequence "aa" and associates capture group 1 with the subsequence "aa" and capture group 2 with an empty sequence.

15.3.22. Unicode Escape Sequence

A Unicode escape sequence is a backslash followed by the letter 'u' followed by four hexadecimal digits (0-9a-fA-F). This sequence matches a character in the target sequence with the value specified by the four digits. For example:

  • "\u0041" matches the target sequence "A".

15.3.23. Wildcard Character

A wildcard character matches any character in the target expression except a newline.

15.3.24. Word Boundary Assert

A word boundary assert matches if the current position in the target sequence is immediately after a word boundary. A word boundary occurs in the following situations.

  • The current position is at the beginning of the target sequence, and the current character is one of the word characters 0-9a-zA-Z _.

  • The current position is at the end of the target sequence, and the last character in the target sequence is one of the word characters.

  • The character at the current position is one of the word characters, and the preceding character is not.

  • The character at the current position is not one of the word characters, and the preceding character is.


Section 15.4. About the Exercises

15.4. About the Exercises

We haven't looked yet at the details of the various templates and classes in the header <regex>, so it's difficult to write code that uses them. Instead, for these exercises, use the header "rgxutil.h", which provides simple functions for checking regular expression syntax and for regular expression matching. The function match_ECMA uses the ECMAScript grammar; the function match_grep uses the grep grammar; and the function match_ere uses the ERE grammar. The header is available on my Web site in the archive that contains the examples. In addition, its contents are listed in Appendix B.3.

To check the syntax of a regular expression, write the regular expression as a C-style string, and pass it to one of the functions match_ECMA, match_grep, or match_ere.

Example 15.1. Checking Syntax (regexgram/check.cpp)

// demonstrate use of match_XXX functions to check regular expression syntax
#include "rgxutil.h"

int main ()
  { // demonstrate functions match_XXX
  const char expr [] = "a*";
  match_ECMA (expr);
  match_grep (expr);
  match_ere (expr);

  match_ECMA ("*");
  match_grep ("*");
  match_ere ("*");
  return 0;
  }

To check whether a regular expression matches some target text, write both the regular expression and the target text as C-style strings, and pass them to one of the functions match_ECMA, match_bre, or match_ere.

Example 15.2. Matching (regexgram/match.cpp)

// demonstrate use of match_XXX functions for regular expression searching
#include "rgxutil.h"

int main ()
  { // demonstrate functions match_XXX
  match_ECMA ("[b-z]",  "b");
  match_grep ("[b-z]",  "b");
  match_ere ("[b-z]",  "b");

  match_ECMA ("[b-z]",  "c");
  match_grep ("[b-z]",  "c");
  match_ere ("[b-z]",  "c");

  match_ECMA ("[b-z]",  "a");
  match_grep ("[b-z]",  "a");
  match_ere ("[b-z]",  "a");

  match_ECMA ("[b-z]",  "B");
  match_grep ("[b-z]",  "B");
  match_ere ("[b-z]",  "B");
  return 0;
  }


Exercises

Exercise 1

The best way to learn about the details of regular expressions is to use them. If you're confused by any of the examples in this chapter, try them out with the various match functions. Be careful of backslashes: In a C-style string, you need two for each one in the regular expression.

Exercise 2

For each of the following target sequences, write a regular expression using the ECMAScript grammar and a regular expression using the grep grammarthey will often be the samethat matches it and nothing else:

  1. The letter 'a'

  2. The letter 'b'

  3. The letter 'a' followed by the letter 'b'

  4. Any character

  5. Any character followed by any character

  6. Any vowel

  7. Any character that is not a vowel

  8. Any of the characters 'b', 'c', 'd', 'e', 'f', 'g', 'h'

  9. Any letter of the alphabet

  10. The character '{'

  11. The character '\'

  12. Any character followed by the same character

  13. Any letter except 'Q'

  14. Any letter except 'Q' and 'x'

  15. Any number of occurrences of the letter 'a'

  16. Any number of occurrences of the letter sequence "ab"

  17. Any number of occurrences of either of the letters 'a' and 'b'

  18. Zero or one occurrence of either of the letters 'a' and 'b'

  19. One or more occurrences of either of the letters 'a' and 'b'

  20. Seventeen or more occurrences of either of the letters 'a' and 'b'

  21. One of the three HTML tags "<EM>", "<CODE>", and "<PRE>"; don't make allowances for lowercase characters

  22. One of those same three HTML tags, followed by an arbitrary sequence of characters that does not include a '<', followed by the corresponding closing tag ("</EM>", "</CODE>", or "</PRE>")

Exercise 3

How many ways can you think of to write a regular expression that matches any of the target sequences "0", "1", and "2"?

Exercise 4

How many ways can you think of to write a regular expression that matches a single hexadecimal digitany decimal digit or any of the letters 'a' tHRough 'f', either lowercase or uppercase?

Exercise 5

  1. Write a regular expression that matches a sequence of three characters followed by the same three characters in the same order.

  2. Write a regular expression that matches a sequence of three characters followed by the same three characters in reverse order.


Chapter 16. Regular Expression Objects

I du believe with all my soul In the gret Press's freedom,
To pint the people to the goal An' in the traces lead 'em.

"The Bigelow Papers"
JAMES RUSSELL LOWELL

All the operations that involve regular expressions begin with an object of a type that is an instantiation of the class template basic_regex. This object holds the regular expression to be matched. It's passed as an argument to the search functions (Chapter 17) and to the constructors of the regular expression iterators (Chapter 19).

The template takes two type arguments. The first, referred to as Elem in this chapter, is the type of the characters that the regular expression object will traffic in. The most common element types are, of course, char and wchar_t. Two typedefs, named regex and wregex, respectively, can be used to create regular expression objects for sequences of characters of these two types. Thus, you can create regular expression objects for ordinary characters with the type basic_regex<char> or with the type regex; they mean the same thing.

The second type argument is a traits class, which we look at in detail in Chapter 21. This traits class has a default type of regex_traits<Elem>, so basic_regex<char> is shorthand for basic_regex<char, regex_traits<char> >. The class template regex_traits has explicit instantiations in the TR1 library for elements of type char and wchar_t. Other element types have no requirements. So if you want to use basic_regex for any element type other than char or wchar_t, you'll have to provide your own traits class.[1]

[1] Well, not necessarily. Implementations of the TR1 library are allowedbut not required to provide traits classes in addition to the ones needed for char and wchar_t. But for portable code, you need your own traits class for any type other than char or wchar_t.


Section 16.1. Definitions

16.1. Definitions

A bitmask type is defined by the library implementation. Values of a bitmask type can be combined with the | operator to create new values that represent the union of the values specified by the operands and with the & operator to create new values that represent the intersection of the values specified by the operands.

An enumeration type is defined by the library implementation. It provides a set of named constants.

An empty regular expression does not match any character sequence.

The constructors, the assignment operators, and the assign member functions for objects of type basic_regex<Elem> all take an operand sequence that designates the regular expression that the resulting object will hold. The constructors and the assign member functions also take an additional argument that designates the regular expression grammar to use to interpret the operand sequence, as well as some optional flags to permit optimizations and to modify the meaning of some elements of the regular expression grammar. These functions all throw an object of type regex_error (see Section 16.6) if the operand sequence is not a valid regular expression.

In the descriptions of these functions, the names of the arguments are used to describe the form of the operand sequence:

  • ptr: a null-terminated sequence of characters of type Elemsuch as a C string, when Elem is type charbeginning at ptr, which must not be a null pointer, where the terminating element is the value Elem() and is not part of the operand sequence

  • ptr, count: a sequence of count characters of type Elem beginning at ptr, which must not be a null pointer

  • str: the sequence specified by the basic_string<Elem> object str

  • first, last: a sequence of characters of type Elem delimited by the iterators first and last, in the range [first, last)

  • right: the basic_regex<Elem> object right

For example, the constructor

explicit basic_regex( const Elem *ptr,
  flag_type flags = ECMAScript)

constructs a basic_regex<Elem> object from a null-terminated character sequence:

basic_regex<char> rgx("a*b"); // rgx holds regular expression "a*b"

The constructor

basic_regex(const Elem *ptr, size_type count,
  flag_type flags = ECMAScript)

constructs a basic_regex<Elem> object from a C-style array and a character count:

basic_regex<char> rgx("a*b", 2);
                               // rgx holds regular expression "a*"

The constructor

template<class STraits, class STalloc>
explicit basic_regex(
  const basic_string<Elem, STraits, STalloc>& str,
  flag_type flags = ECMAScript)

constructs a basic_regex<Elem> object from a C++ basic_string<Elem> object:

string str("a*b");
basic_regex<char> rgx(str);   // rgx holds regular expression "a*b"

The constructor

template<class InIt>
basic_regex(InIt first, InIt last,
  flag_type flags = ECMAScript)

constructs a basic_regex<Elem> object from a pair of iterators:

vector<char> vec;
vec.push_back('a');
vec.push_back('*');
vec.push_back('b');
basic_regex<char> rgx(vec.begin(), vec.end());
                              // rgx holds regular expression "a*b"

And the constructor

basic_regex(const basic_regex <Elem>& right)

constructs a basic_regex<Elem> object from another basic_regex<Elem> object:

basic_regex<char> rgx("a*b"); // rgx holds regular expression "a*b"
basic_regex<char> rgy("a*b"); // rgy holds regular expression "a*b"


Section 16.2. Header <regex> Partial Synopsis

16.2. Header <regex> Partial Synopsis

In this chapter, we look at the following components of the header <regex>:

namespace std {   // C++ standard library
 namespace tr1 {  // TR1 additions

    // bitmask_type syntax_option_type
namespace regex_constants {
  typedef bitmask_type syntax_option_type;
  static const syntax_option_type
    awk, basic, collate, ECMAScript, egrep,
    extended, grep, icase, nosubs, optimize;
  }

    // CLASS TEMPLATE basic_regex
template<class Elem,
    class RXtraits = regex_traits<Elem> >
    class basic_regex;
typedef basic_regex<char> regex;
typedef basic_regex<wchar_t> wregex;

    // FUNCTION TEMPLATE swap
template<class Elem, class RXtraits>
    void swap(basic_regex <Elem, RXtraits>& left,
        basic_regex <Elem, RXtraits>& right) throw ();

    // enumeration_type error_type
namespace regex_constants {
  typedef enumeration_type error_type;
  static const error_type error_backref, error_badbrace,
    error_badrepeat, error_brace, error_brack,
    error_collate, error_complexity, error_ctype,
    error_escape, error_paren, error_range,
    error_space, error_stack;
  }

    // CLASS regex_error
class regex_error;

} }


Section 16.3. Syntax Options

16.3. Syntax Options

namespace regex_constants { // regular expression constants
  typedef bitmask_type syntax_option_type;
  static const syntax_option_type
    awk, basic, collate, ECMAScript, egrep,
    extended, grep, icase, nosubs, optimize;
}

The type is a bitmask type that designates various combinations of a regular expression grammar, optimization flags, and syntax modifiers.

Values of type syntax_option_type are passed to members of the class template basic_regex to designate the regular expression grammar to use to interpret the member's operand sequence, to modify the meaning of some elements of the regular expression grammar, and to permit optimizations.

The following constants designate regular expression grammars:

  • ECMAScript: compile as ECMAScript

  • basic: compile as BRE

  • extended: compile as ERE

  • awk: compile as awk

  • grep: compile as grep

  • egrep: compile as egrep

The following constants modify the meaning of some elements of the regular expression grammar:

  • icase: make matches case insensitive

  • collate: make collating locale sensitive

The following constants permit optimizations:

  • nosubs: the implementation need not report the contents of capture groups

  • optimize: the implementation should emphasize speed of matching rather than speed of regular expression compilation

When using these flags, exactly one of the regular expression grammar selectors must be used. Any combination of the other four flags can be logically ORed with the grammar selector to make a valid flags argument.

These names are defined in the namespace regex_constants, which is embedded in the namespace std::tr1. As a result, the fully qualified names for these constants are rather longwinded. For convenience, these constants are also available in the class template basic_regex, so you can get them from either place. For example, in all the following expressions, the identifier icase means the same thing:

std::tr1::regex_constants::icase;
std::tr1::basic_regex::icase;
using std::tr1::basic_regex;
basic_regex::icase;
using namespace std::tr1;
regex_constants::icase;
using namespace std::tr1::regex_constants;
icase;

16.3.1. Case-Insensitive Comparisons

Ordinarily, a character in a regular expression matches a character in the target text if the two characters have the same numeric value. For example, in the ASCII encoding, the character "a" has the value 0x61. A regular expression object regex rgx("a") will match the target text "a" and the target text "\x61" because they both have the same numeric value as the 'a' in the regular expression. It will not match the target text "A" or the target text "\x41", which is the ASCII code for 'A'.

If you pass the flag icase along with the text of the regular expression, characters will be compared for equality by converting each of them to lower-case and comparing the results. A regular expression object regex rgx("a", ECMAScript | nocase) will match the target text "a" and the target text "\x61", as well as the target text "A" and the target text "\x41".[2]

[2] The conversion to lowercase is done by calling use_facet<ctype<Elem> >(getloc()).tolower(ch). We look at that call in more detail in Chapter 21; for now, it converts the character ch to lowercase in accordance with the rules for the traits object's current locale. That is, case-insensitive comparisons depend on the locale.

The icase flag applies only to individual character comparisons. It does not change the meaning of the characters used to define a character range. Thus, the character range "[a-c]" represents the characters 'a', 'b', and 'c', with or without the icase flag. Of course, when you look for a match with the icase flag, that set of three characters will match uppercase as well as lowercase characters.[3]

[3] That may sound like a distinction without a difference, but when writing character ranges, it's important to understand which characters are represented by the range. The regular expression "[A-z]" doesn't change meaning with the icase flag. Either way, it's probably a mistake.

Example 16.1. The icase Flag (regexbasic/icase.cpp)

# include <regex>
# include <iostream>
using std::tr1::regex;
using std::tr1::regex_match;
using namespace std::tr1::regex_constants;
using std::cout;

static void match(const char * title,
const char *expr, const char * tgt,
  syntax_option_type flags)
  { // check for match
  regex rgx(expr, flags);
  cout << '`' << expr << "` (" << title << "): ";
  if (regex_match(tgt, rgx))
    cout << "matched";
  else
    cout << "didn't match";
  cout << " ` " << tgt << " `\n";
  }

static void match4(const char * title, const char * expr,
  syntax_option_type flags)
  { // check four matches
  match(title, expr, "a", flags);
  match(title, expr, "\ x61 ", flags);
  match(title, expr, "A", flags);
  match(title, expr, "\ x41 ", flags);
  }

int main ()
  { // demonstrate icase flag
  match4("case sensitive", "a", ECMAScript);
  match4("case insensitive", "a", ECMAScript | icase);
  match4("case sensitive", "[a-c]", ECMAScript);
  match4 ("case insensitive", "[a-c]",
    ECMAScript | icase);
  return 0;
  }

16.3.2. Character Ranges and the collate Flag

The collate flag does, however, change the rules for defining and testing character ranges. As we saw in Chapter 15, a character range is defined by writing the first and last characters, separated by a dash, inside a bracket expression. For example, the regular expression "[0-2]", in the C locale, matches any of the characters '0', '1', or '2'.[4] The rule is that for a character range whose end points are ch1 and ch2, a character ch is in the range if ch1 <= ch && ch <= ch2. The relative order of characters is determined by the relative order of their internal representation.

[4] In the C locale, the representations of the digits '0' through '9' are required to be contiguous and increasing. That's also why you can translate single digits into numeric values with ch - '0'.

For many writing systems, that rule doesn't work. We saw an example of this in Chapter 15, when we talked about character ranges. In the EBCDIC encoding, there are nonalphabetic characters represented by values between the values that represent 'i' and 'j', so a regular expression like "[h-k]" will end up including unexpected characters in the range.

Another example occurs with character encodings such as ISO-8859-1, which supplements the ASCII encoding with characters whose representations have values that are greater than 127.[5] The character 'a' is represented by the value 0x61; the character 'c' is represented by the value 0x63. So if we ask whether the regular expression "[a-c]" matches the target sequence "â", the answer would be no, because the representation of 'â' is 0xE2, which is not in the range [0x61, 0x63].

[5] In ASCII, characters are represented by 7 bits, so the representations in the ASCII character set are all in the range [0, 127].

To fix both of these problems, make the definition of the range locale sensitive with collate. The test for inclusion in a range then involves an extra level of indirection: Each character ch is translated into a collating element by calling

use_facet<collate<Elem> >(
  getloc()).transform(&ch, & ch + 1)

which returns an object of type std::basic_string<Elem>. These returned strings are then compared, and the result determines whether a character is in the range. If we refer to that rather unwieldy expression as TRANS(ch), the test for inclusion in a range whose end points are ch1 and ch2 is TRANS(ch1) <= TRANS(ch) && TRANS(ch) <= TRANS(ch2). In the ISO-8859-1 locale, this more complicated test will correctly put 'â' in the range "[a-c]".

16.3.3. The nosubs Flag

In Chapter 18, we look at the class template match_results. You can pass a match_results object to the regular expression search functions; on a successful search, the function will fill in details about the text that each capture group matched. For example, when matching the regular expression "a(.*)d" to the text "abcd", the match_results object will tell you that the first capture group matched the text "bc". That information is often important, but sometimes doesn't matter. In that case, you can use the flag nosubs to generate a basic_regex object that will not report the details of capture groups. That can make matching significantly faster.[6]

[6] The TR1 library specification doesn't talk about raw matching speed, so there are no formal requirements here. However, this flag makes it possible in many cases to simplify the internal representation of the regular expression object and to simplify the algorithm used to detect matches.

16.3.4. Optimizing Searches

When you generate a regular expression object, the library code scans the sequence of characters that defines the regular expression and converts it into an internal representation.

The internal representation usually takes one of two general forms. The one that's more difficult to create can produce faster searches. Passing the optimize flag when you generate a regular expression object asks for fast searching, even if that means taking longer to build the internal representation. Just as with the nosubs flag, there is no enforceable requirement here. But if you need fast searches, it doesn't hurt to ask.[7]

[7] This optimization typically means converting a nondeterministic finite automaton into a deterministic finite automaton. There are well-understood algorithms for doing this. Unfortunately, this conversion can sometimes be very complex; hence, very slow. So don't ask for it if you don't need it.


Section 16.4. The basic_regex Class Template

16.4. The basic_regex Class Template

template<class Elem,
  class RXtraits = regex_traits<Elem>
  class basic_regex {
public:

  basic_regex();
  explicit basic_regex(const Elem *ptr,
    flag_type flags = ECMAScript);
  basic_regex(const Elem *ptr, size_type count,
    flag_type flags = ECMAScript);
  basic_regex(const basic_regex& right);
  template<class STtraits, class STalloc>
    explicit basic_regex(
      const basic_string<Elem, STtraits, STalloc>& str,
      flag_type flags = ECMAScript);
  template<class InIt>
    explicit basic_regex(InIt first, InIt last,
      flag_type flags = ECMAScript);

  basic_regex& operator=(const Elem *ptr);
  template<class STtraits, class STalloc>
    basic_regex& operator=(
      const basic_string <Elem, STtraits, STalloc >& str);
  basic_regex& operator=(const basic_regex& right);
  basic_regex& assign(const Elem *ptr,
    flag_type flags = ECMAScript);
  basic_regex& assign(const Elem *ptr, size_type count,
    flag_type flags = ECMAScript);
  template<class STtraits, class STalloc>
  basic_regex& assign(
    const basic_string <Elem, STtraits, STalloc >& str,
    flag_type flags = ECMAScript);
  template<class InIt>
    basic_regex& assign(InIt first, InIt last,
      flag_type flags = ECMAScript);
      basic_regex& assign(const basic_regex& right);

  void swap(basic_regex& other) throw();

  locale_type imbue(locale_type loc);
  locale_type getloc() const;

  unsigned mark_count() const;
  flag_type flags() const;

  typedef Elem value_type;
  typedef regex_constants::syntax_option_type flag_type;
  typedef typename RXtraits::locale_type locale_type;

  static const flag_type ECMAScript =
    regex_constants::ECMAScript;
  static const flag_type basic =
    regex_constants::basic;
  static const flag_type extended =
    regex_constants::extended;
  static const flag_type grep =
    regex_constants::grep ;
  static const  flag_type egrep =
    regex_constants::egrep;
  static const flag_type awk =
    regex_constants::awk;

  static const flag_type nosubs =
    regex_constants::nosubs;
  static const flag_type optimize =
    regex_constants::optimize;
  static const flag_type icase =
    regex_constants::icase;
  static const flag_type collate =
    regex_constants::collate;
  };

16.4.1. basic_regex Summary

An object of type basic_regex<Elem> can be created by the template's default constructor or from an operand sequence describing the regular expression that the object will hold. The constructors are discussed in Section 16.4.2 and the meanings of the various operand sequences are discussed in Section 16.1.

The destructor for basic_regex releases all resources used by the object.

You can change a basic_regex object so that it is empty or so that it holds a different regular expression. This is done with operator= or with the assign member functions, discussed in Section 16.4.3.

If a constructor, operator=, or assign fails, either because the operand sequence does not designate a valid regular expression or because there aren't enough resources available, it throws an object of type regex_error. This is discussed in Section 16.6.

You can exchange the contents of two regular expression objects with the member function basic_regex::swap(basic_regex&) and with the non-member function swap(basic_regex&, basic_regex&). These functions are discussed in Section 16.4.4.

A basic_regex object holds a locale object that determines some of the properties of regular expression matching. You can change this locale object with the member function basic_regex::imbue, and you can get a copy of this local object with the member function basic_regex::getloc. These functions are discussed in Section 16.4.5.

You can get the number of capture groups in a regular expression by calling the member function basic_regex::mark_count. You can get a copy of the flags used for the regular expression by calling the member function basic_regex::flags. These functions are discussed in Section 16.4.6.

The template basic_regex defines two nested type names, based on its template type arguments, and repeats several type names and constants that are also defined in the namespace std::tr1::regex_constants. These definitions are discussed in Section 16.4.7.

16.4.2. Creating basic_regex Objects

basic_regex::basic_regex ();

The constructor constructs a basic_regex object that holds an empty regular expression.

explicit basic_regex::basic_regex (const Elem *ptr,
  flag_type flags = ECMAScript);
basic_regex::basic_regex (const Elem *ptr, size_type  count,
  flag_type flags = ECMAScript);
basic_regex__basic_regex(const basic_regex& right);
template<class STtraits, class STalloc>
  explicit basic_regex::basic_regex(
    const basic_string<Elem,  STtraits, STalloc>& str,
    flag_type flags = ECMAScript);
template<class InIt>
  explicit basic_regex::basic_regex(InIt first, InIt last,
    flag_type flags = ECMAScript);

Each of the constructors constructs a basic_regex object that holds a regular expression defined by the constructor's operand sequence interpreted in accordance with the flags argument.

All the flags arguments have a default value of ECMAScript, so the default grammar is ECMAScript. To use a different grammar, pass the constant that represents that grammar to the constructor.

Example 16.2. basic_regex Constructors (regexbasic/construct.cpp)

# include <regex >
# include <string >
using std ::tr1 ::regex;
using std ::string;

int main ()
  { // demonstrate basic regex constructors
  regex  rgx0;                 // default constructor; matches nothing
  char  expr1[] = "abc [d-f]";
  regex rgx1 (expr1);     // holds "abc[d-f]", ECMAScript grammar
  regex rgx2 (expr1, 3);  // holds "abc", ECMAScript grammar
  regex rgx3 (rgx2);      // holds "abc", ECMAScript grammar
  string str ("[def]");
  regex rgx4 (str, regex ::basic);
                          // holds "[def]", BRE grammar
  regex rgx5 (str.begin(), str.end(),
    regex ::basic | regex ::icase);
                          // holds "[def]", BRE grammar,
                          // case insensitive
  return 0;
  }

16.4.3. Assigning basic_regex Objects

basic_regex& basic_regex::operator= (const Elem *ptr);
template<class STtraits, class STalloc>
  basic_regex& basic_regex::operator=(
    const basic_string<Elem, STtraits, STalloc>&str);
basic_regex& basic_regex::operator=(
  const basic_regex& right);

The operators each replace the regular expression held by *this with the regular expression defined by the operand sequence, then return *this.

The first two operators interpret the operand sequence in accordance with the ECMAScript grammar and no additional flags.

You cannot control the grammar or the other flags with an assignment.

Example 16.3. basic_regex Assignment Operators (regexbasic/assign.cpp)

# include <regex>
# include <string>
using  std ::tr1 ::regex;
using  std ::string;

int main()
  { // demonstrate basic_regex assignment operators
  regex rgx;                   // empty regular expression object
  rgx = "abc";                 // holds  "abc", ECMAScript encoding
  string str("[def]");
  rgx = str;                   // holds  "[def]", ECMAScript encoding
  regex rgx1 ("abc [def]",  regex ::basic);
  rgx = rgx1;              // holds  "abc[def]", BRE encoding
  return 0;
  }

basic_regex & basic_regex ::assign ( const Elem * ptr,
  flag_type flags  = ECMAScript);
basic_regex & basic_regex ::assign (
  const Elem * ptr, size_type   count,
  flag_type flags  = ECMAScript);
template < class STtraits, class   STalloc >
basic_regex & basic_regex ::assign (
  const basic_string <Elem, STtraits, STalloc >& str,
  flag_type flags  = ECMAScript);
template < class   InIt >
  basic_regex & basic_regex ::assign ( InIt   first, InIt last,
    flag_type flags =   ECMAScript);
basic_regex & basic_regex ::assign ( const   basic_regex &  right);

Each of the member functions replaces the regular expression held by *this with the regular expression defined by the operand sequence interpreted in accordance with the flags argument, if present.

16.4.4. Swapping basic_regex Objects

void basic_regex ::swap ( basic_regex & other) throw ();
template < class Elem, class RXtraits >
  void swap ( basic_regex <Elem, RXtraits >& left,
    basic_regex <Elem, RXtraits >& right) throw ();

The member function swaps the regular expressions between *this and other.

The non-member function calls left.swap(right).

Example 16.4. Member Function swap (regexbasic/swap.cpp)

#include <regex>
using std::tr1::regex;

int main()
  { // demonstrate use of swap
  regex  rgx0;            // empty regular expression object
  regex  rgx1("abc");     // holds  "abc"
  rgx0 . swap(rgx1);      // rgx0 holds  "abc" and rgx1 is empty
  swap(rgx0, rgx1);       // rgx0 is empty and rgx1 holds  "abc"
  return 0;
  }

16.4.5. Locales

locale_type basic_regex ::imbue ( locale_type loc);
locale_type basic_regex ::getloc () const ;

The first member function empties *this and calls imbue(loc) on the RXtraits object held by *this. The second member function returns a copy of the locale object held by the RXtraits object held by *this.

The interpretation of a regular expression depends on the locale that it was defined with. A basic_regex object does not keep a copy of the character sequence that defined its regular expression. The object can't reinterpret the character sequence in accordance with the new locale, so when you call imbue, it discards the previous regular expression. If you don't want to have an empty basic_regex object, you should provide a new regular expression by assigning from an operand sequence or calling assign or swap.

16.4.6. Access

unsigned basic_regex ::mark_count () const ;

The member function returns the number of capture groups in the regular expression.

When a basic_regex object was created with the flag nosubs, the regular expression engine is not required to keep track of the contents of capture groups. This does not affect the number of capture groups.

Example 16.5. basic_regex::mark_count (regexbasic/markcount.cpp)

# include <regex>
# include <iostream>
using std :: tr1 :: regex ;
using std :: cout ;

void   show_count ( const char * title, const regex & rgx)
  {
  cout << ' \" ' <<  title <<  " \" has " <<  rgx.mark_count ()
    <<  " capture group "
    <<  ( rgx . mark_count () == 1 ? "" : "s")
    <<  ".\n";
  }

void show ( const char * expr)
  {
  regex rgx ( expr);
  show_count (expr, rgx);
  }

int main ()
  { // demonstrate use of mark_count
  show ("");
  show (" abc ");
  show ("( abc)");
  show ("(a)b(c)");
  show ("(a(b)c)");
  return 0;
  }

flag_type basic_regex ::flags () const ;

The member function returns a copy of the flags argument that was passed when the regular expression was defined. If *this is empty, it returns 0.

Example 16.6. basic_regex::flags (regexbasic/flags.cpp)

# include <regex >
# include < iostream >
using std :: tr1 :: regex ;
using std :: cout ;

void   show_flags ( const regex & rgx)
  {   // extract and show flag values
  regex :: flag_type flags = rgx . flags ();
  if (( flags & regex :: ECMAScript) == regex :: ECMAScript)
    cout << " ECMAScript ";
  else if (( flags & regex :: basic) == regex :: basic)
    cout << " basic ";
  else if (( flags & regex :: extended) == regex :: extended)
    cout << " extended ";
  else if (( flags & regex :: grep) == regex :: grep)
    cout << " grep ";
  else if (( flags & regex :: egrep) == regex :: egrep)
    cout << " egrep ";
  else if (( flags & regex :: awk) == regex :: awk)
    cout << "awk ";
  else
    cout << " unknown grammar ";
  if (( flags & regex :: icase) == regex :: icase)
    cout << " | icase ";
  if (( flags & regex :: collate) == regex :: collate)
    cout << " | collate ";
  if (( flags & regex :: nosubs) == regex :: nosubs)
    cout << " | nosubs ";
  if (( flags & regex :: optimize) == regex :: optimize)
    cout << " | optimize ";
  cout <<   ' \n ' ;
  }

int main ()
  {   // demonstrate member function basic_regex::flags
  regex  rgx ;
  show_flags (rgx);
  rgx . assign ("", regex :: grep | regex :: nosubs);
  show_flags (rgx);
  rgx =   "a";
  show_flags (rgx);
  return 0;
  }

16.4.7. Nested Types and Flags

typedef Elem   basic_regex ::value_type ;
typedef   regex_constants :: syntax_option_type
  basic_regex ::flag_type ;
typedef typename RXtraits :: locale_type
  basic_regex ::locale_type ;

The first typedef is a synonym for the template argument Elem. The second typedef is a synonym for the type regex_constants::syntax_option_-type. The third typedef is a synonym for the type locale_type, defined in the template argument RXtraits.

static const flag_type basic_regex ::ECMAScript   =
  regex_constants :: ECMAScript ;
static const flag_type basic_regex :: basic =
  regex_constants :: basic ;
static const flag_type basic_regex ::extended   =
  regex_constants :: extended ;
static const flag_type basic_regex ::grep   =
  regex_constants ::grep ;
static const flag_type basic_regex :: egrep =
  regex_constants :: egrep ;
static const flag_type basic_regex :: awk =
  regex_constants :: awk ;

static const flag_type basic_regex :: nosubs =
  regex_constants :: nosubs ;
static const flag_type basic_regex ::optimize =
  regex_constants :: optimize ;

static const flag_type basic_regex ::icase =
  regex_constants :: icase ;
static const flag_type basic_regex ::collate   =
  regex_constants :: collate ;

These constants are self-explanatory. They duplicate the values of some of the constants defined in the namespace std::tr1::regex_constants. Writing regex::basic is shorter than writing std::tr1::regex_constants::basic.


Section 16.5. Predefined basic_regex Types

16.5. Predefined basic_regex Types

typedef basic_regex <char> regex ;
typedef basic_regex <wchar_t> wregex ;

The typedefs are synonyms for basic_regex<char> and basic_regex <wchar_t>, respectively.

These are the types you'll use most often.


Section 16.6. Error Handling

16.6. Error Handling

Some members of basic_regex and some global function templates throw an object of type regex_error when a runtime error occurs. The object holds a value of type regex_constants::error_type that indicates what the error was.

namespace regex_constants {
  typedef enumeration_type error_type ;
  static const error_type error_backref, error_badbrace,
    error_badrepeat, error_brace, error_brack,
    error_collate, error_complexity,   error_ctype,
    error_escape, error_paren, error_range,
    error_space, error_stack ;
  }

The typedef error_type designates an implementation-defined integral type that can be used to designate an error. The values that this type can take on are

  • error_backref: the regular expression contained an invalid back reference.

  • error_badbrace: the regular expression contained an invalid value in a repetition count.

  • error_badrepeat: a repetition symbolone of *, ?, +, and { in ECMAScriptwas not preceded by an expression.

  • error_brace: the opening symbol or the closing symbol of a repetition count was not properly matched.

  • error_brack: the opening symbol or the closing symbol of a bracket expression was not properly matched

  • error_collate: the regular expression contained an invalid collating element name.

  • error_complexity: an attempted match failed because it was too complex.

  • error_ctype: the regular expression contained an invalid character class name.

  • error_escape: the regular expression contained an invalid character escape sequence.

  • error_paren: the opening symbol or the closing symbol of a capture group was not properly matched.

  • error_range: the regular expression contained an invalid character range specifier.

  • error_space: parsing the regular expression failed because not enough resources were available.

  • error_stack: an attempted match failed because not enough memory was available.

class regex_error : public std :: runtime_error {
public :
  explicit regex_error ( regex_constants :: error_type error);
  regex_constants :: error_type code () const ;
  };

When an error occurs in parsing a regular expression or when matching a regular expression to a target sequence, the library code throws an object of type regex_error.

The member function regex_error::code returns a value of type regex_-constants::error_type that indicates the nature of the error.

Example 16.7. Catching regex_error (regexbasic/error.cpp)

# include <regex >
# include <iostream>
using std :: tr1 :: regex ; using std :: tr1 :: regex_error ;
using std :: cout ;

const char * get_error (
  std :: tr1 :: regex_constants :: error_type code)
  {   // translate error code to text
  switch ( code)
    { // select text
    case std :: tr1 :: regex_constants :: error_backref :
      return " invalid back reference ";
    case std :: tr1 :: regex_constants :: error_badbrace :
      return " invalid repetition  count ";
    case std :: tr1 :: regex_constants :: error_badrepeat :
      return " repeat not preceded by  expression ";
    case std :: tr1 :: regex_constants :: error_brace :
      return " unmatched curly  brace ";
    case std :: tr1 :: regex_constants :: error_brack :
      return " unmatched square  bracket ";
    case std :: tr1 :: regex_constants :: error_collate :
      return " invalid collating element name ";
    case std :: tr1 :: regex_constants :: error_complexity :
      return " match too complex ";
    case std :: tr1 :: regex_constants :: error_ctype :
      return " invalid character class name ";
    case std :: tr1 :: regex_constants :: error_escape :
      return " invalid character escape  sequence ";
    case std :: tr1 ::  regex_constants :: error_paren :
      return " unmatched  parenthesis ";
    case std :: tr1 :: regex_constants :: error_range :
      return " invalid range specifier ";
    case std :: tr1 :: regex_constants :: error_space :
      return " insufficient resources ";
    case std :: tr1 :: regex_constants :: error_stack :
      return " out of memory ";
    default :
      return " unknown ";;
    }
  }

void test ( const char * expr)
  {   // construct regex object, catch exception
  cout <<  ' ` '  << expr << " ', ";
  try
    {   // try to construct regex object with invalid regular expression
    regex rgx ( expr);
    cout << " okay \n";
    }
  catch ( const regex_error & error)
    {   // catch regex  error object
    cout << get_error ( error . code ()) < <   ' \n ' ;
    }
  }

int main ()
  {   // demonstrate use of error_type
  test ("a{3,1} ");
  test ("[b-a]");
  return 0;
  }


Exercises

Exercise 1

For each of the following errors, write a simple test case containing the error, and try to compile it. In the error messages, look for the key words that relate to the error in the code.

  1. Attempting to construct a basic_regex<Elem> object from a C-style array holding a character type that is different from Elem

  2. Attempting to construct a basic_regex<Elem> object from a basic_-string<Other> object, where Other is different from Elem

  3. Attempting to construct a basic_regex<Elem> object from two iterators of different types

  4. Attempting to swap two basic_regex objects with different character types

  5. Constructing a basic_regex object using a grammar flag without the appropriate namespace qualifiers

  6. Constructing a basic_regex object using a grammar flag and an option flag without the appropriate namespace qualifiers

Exercise 2

Expand Example 16.7 by adding regular expressions to generate all the error codes except error_complexity, error_space, and error_stack.

Exercise 3

Write a program that constructs a regex object from the text on its command line.

Exercise 4

Write a program that uses std::getline to read a line of text from the standard input stream into a std::string object, and construct a regex object from that text.

Exercise 5

Write a program that uses std::getline to read a line of text from a file named "input.txt" into a std::string object, and construct a regex object from that text.

Exercise 6

Write a program that uses two objects of type std::istream_-iterator<char> to read text from a file named "input.txt", and construct a regex object directly from that textthat is, don't use a string object or any other kind of intermediate storage.


Chapter 17. Searching

There are and can be only two ways of searching into and discovering truth.

Novum Organum
FRANCIS BACON

Suppose that you want to scan a text file encoded in HTML and extract all the lines that contain code snippets. Each snippet begins with "<CODE>" and ends with "</CODE>". The two markers are not case sensitive. For now, let's assume that no snippet is longer than one line. This means that we need to search only for lines that contain the first marker, so we can use this text to define a regular expression for the search:

const char *expr = "<CODE>";

It's easy to read a file one line at a time, so we don't need to do anything more sophisticated in the regular expression to pick out lines. Simply read a line and see whether it has any text that matches the regular expression. To check for that match, we'll call the template function regex_search, passing it the current line of text from the file and the regular expression object. The function returns true if any subsequence in the target text matches the regular expression.

Example 17.1. Searching for Lines with Code Snippets (regexsrch/snippets.cpp)

#include <regex>
#include <iostream>
#include <fstream>
#include <string>
#include <stdlib.h>
using std::tr1::regex; using std::tr1::regex_search;
using std::string; using std::ifstream; using std::cout;

static void show_matches (const char *fname)
  { // scan file named by fname, line by line
  ifstream input (fname);
  string str;
  const char *expr = "<CODE>";
  regex rgx (expr, regex::icase);
  while (getline (input, str))
    { // check line for match
    if (regex_search (str, rgx))
      cout << str << '\n';
    }
  }

int main (int argc, char *argv[])
  { // search for lines with code snippets in text file
  if (argc != 2)
    { // wrong number of arguments
    cout << "Usage : snippets <filename>\n";
    return EXIT_FAILURE ;
    }
  try
    { // search the file
    show_matches (argv[1]);
    }
  catch (...)
    { // something went wrong
    cout << "Error\n";
    return EXIT_FAILURE;
    }
  return 0;
  }

There are two ways of searching with regular expressions. You can ask whether a regular expression exactly matches the entire target sequence, and you can ask whether a regular expression matches a subsequence of the target sequence. The first is done with the overloaded set of function templates regex_match, discussed in Section 17.2; the second is done with the overloaded set of function templates regex_search, discussed in Section 17.3.

The argument lists for the regex_match and regex_search function templates all start with one or two arguments that designate the sequence of characters to be searched. This target sequence is followed by a basic_regex object that defines the regular expression to search for. Finally, an argument of type match_flag_type affects the matching rules. This argument has a default value of match_default, so you often don't have to mention it.

In this chapter, we look at three overloaded versions of regex_match and three overloaded versions of regex_search. For each of these six function templates, a corresponding function template can take the same arguments and an additional argument whose type is an instantiation of match_results, which the algorithm fills in with details of how the match was accomplished. We look at those versions in the next chapter.

The characters in the target sequence must have the same type as the element type of the basic_regex object. For example, when the regular expression that you're searching for is held in a basic_regex<wchar_t> object, the target sequence must consist of characters of type wchar_t.

When you call these functions, you can specify the target sequence in three ways.

  1. A pointer ptr of type Elem* designates a null-terminated sequence, such as a C string, when Elem is a synonym for char. The sequence contains the characters in the contiguous array beginning at ptr and ending with the first character whose value is Elem(), which typically has the value 0 and is not part of the target sequence.

  2. An object of type std::basic_string<Elem> designates the character sequence managed by the basic_string object.

  3. A pair of bidirectional iterators first and last designates the character sequence defined by the half-open range [first, last).

Example 17.2. Target Sequences (regexsrch/targets.cpp)

#include <regex>
#include <iostream>
#include <list>
#include <string>
using std::tr1::regex; using std::tr1::regex_match;
using std::cout;
using std::list;
using std::basic_string;

int main()
  { // designating the target sequence
  regex rgx("b(c*)d");

  // pointer
  const char *tgt1 = "bcd";
  if (regex_match(tgt1, rgx))
    cout << "Matches .\n";
  else
    cout << "Doesn' t match .\n";

  // string
  basic_string <char> tgt2("bcd");
  if (regex_match(tgt2, rgx))
    cout << "Matches .\n";
  else
    cout << "Doesn' t match .\n";

  // pair of bidirectional iterators
  list <char> tgt0;
  tgt0.push_back('b');
  tgt0.push_back('c');
  tgt0.push_back('d');
  if (regex_match(tgt0.begin(), tgt0.end(), rgx))
    cout << "Matches .\n";
  else
    cout << "Doesn' t match .\n";

  return 0;
  }


Section 17.1. Header <regex> Partial Synopsis

17.1. Header <regex> Partial Synopsis

In this chapter, we look at the following components of the header <regex>:

namespace std {  // C++ standard library
 namespace tr1 { // TR1 additions

    // FUNCTION TEMPLATE regex_match
template<class Elem, class RXtraits>
  bool regex_match(
    const Elem *ptr,
    const basic_regex<Elem, RXtraits>& rgx,
    match_flag_types flags = match_default);
template<class IOtraits, class IOalloc,
    class Elem, class RXtraits>
  bool regex_match(
    const basic_string<Elem, IOtraits, IOalloc>& str,
    const basic_regex<Elem, RXtraits>& rgx,
    match_flag_types flags = match_default);
template<class BidIt, class Elem, class RXtraits>
  bool regex_match(
    BidIt first, Bidit last,
    const basic_regex<Elem, RXtraits>& rgx,
    match_flag_types flags = match_default);

    // FUNCTION TEMPLATE regex_search
template<class Elem, class RXtraits>
  bool regex_search(
    const Elem *ptr,
    const basic_regex<Elem, RXtraits>& rgx,
    match_flag_types flags = match_default);
template<class IOtraits, class IOalloc,
    class Elem, class RXtraits>
  bool regex_search(
    const basic_string<Elem, IOtraits, IOalloc>& str,
    const basic_regex<Elem, RXtraits>& rgx,
    match_flag_types flags = match_default);
template<class BidIt, class Elem, class RXtraits>
  bool regex_search(
    BidIt first, Bidit last,
    const basic_regex<Elem, RXtraits>& rgx,
    match_flag_types flags = match_default);
} }


Section 17.2. Matching Exactly

17.2. Matching Exactly

template<class Elem, class RXtraits>
  bool regex_match (
    const Elem *ptr,
    const basic_regex <Elem, RXtraits>& rgx,
    match_flag_types flags = match_default);
template<class IOtraits, class IOalloc,
    class Elem, class RXtraits>
  bool regex_match (
    const basic_string <Elem, IOtraits, IOalloc>& str,
    const basic_regex <Elem, RXtraits>& rgx,
    match_flag_types flags = match_default);
template<class BidIt, class Elem, class RXtraits>
  bool regex_match (
    BidIt first, Bidit last,
    const basic_regex <Elem, RXtraits>& rgx,
    match_flag_types flags = match_default);

The function templates return true only if the regular expression argument rgx matches the entire target sequence.

Example 17.3. Using regex_match (regexsrch/match.cpp)

#include <regex>
#include <iomanip>
#include <iostream>
using std::tr1::regex; using std::tr1::regex_match;
using std::cout; using std::setw;

void show_match (const regex & rgx, const char *str)
  { // check for match
  cout << setw (10) << str <<": ";
  if (regex_match (str, rgx))
    cout << "matches\n";
  else
    cout << "doesn' t match\n";
  }

int main()
  { // demonstrate exact match
  regex rgx("b(c*) d");
  show_match(rgx, "bd");                        // matches
  show_match(rgx, "d");                         // doesn't match
  show_match(rgx, "bcd");                     // matches
  show_match(rgx, "bc");                      // doesn't match
  show_match(rgx, "abd");                     // doesn't match
  show_match(rgx, "bde");                     // doesn't match
  return 0;
  }


Section 17.3. Searching

17.3. Searching

template<class Elem, class RXtraits>
  bool regex_search (
    const Elem *ptr,
    const basic_regex <Elem, RXtraits>& rgx,
    match_flag_types flags = match_default);
template<class IOtraits, class IOalloc,
    class Elem, class RXtraits>
  bool regex_search (
  const basic_string <Elem, IOtraits, IOalloc>& str,
    const basic_regex <Elem, RXtraits>& rgx,
    match_flag_types flags = match_default);
template<class BidIt, class Elem, class RXtraits>
  bool regex_search (
    BidIt first, Bidit last,
    const basic_regex <Elem, RXtraits>& rgx,
    match_flag_types flags = match_default);

The function templates return true only if the regular expression argument rgx matches a subsequence of the target sequence.

Example 17.4. Using regex_search (regexsrch/search.cpp)

#include <regex>
#include <iomanip>
#include <iostream>
using std::tr1::regex; using std::tr1::regex_search;
using std::cout; using std::setw;

void show_match ( const regex & rgx, const char *str)
  { // check for match
  cout << setw (10) << str << ": ";
  if (regex_search (str, rgx))
    cout << "matches \n";
  else
  cout << "doesn't match \n";
  }

int main()
  { // demonstrate use of regex_search
  regex rgx ("b(c*) d");
  show_match (rgx, "bd");                        // matches
  show_match (rgx, "d");                         // doesn't match
  show_match (rgx, "bcd");                       // matches
  show_match (rgx, "bc");                        // doesn't match
  show_match (rgx, "abd");                       // matches
  show_match (rgx, "bde");                       // matches
  return 0;
  }


Section 17.4. Search Options

17.4. Search Options

namespace regex_constants {
  static const match_flag_type
    match_default,
    match_not_bol,
    match_not_eol,
    match_not_bow,
    match_not_eow,
    match_any,
    match_not_null,
    match_continuous,
    natch_prev_avail ;
}

Values of type match_flag_type can be combined with the logical OR operator and passed to the various search algorithms. Flags that are not applicable to a particular grammar are ignored when that grammar was used to create the regular expression object used for the search. The flag values have the following meanings:

  • match_default: use normal matching rules.

  • match_not_bol: do not treat the first position in the target sequence as the beginning of a line.

  • match_not_eol: do not treat the last position in the target sequence as the end of a line.

  • match_not_bow: do not treat the first position in the target sequence as the beginning of a word.

  • match_not_eow: do not treat the last position in the target sequence as the end of a word.

  • match_any: if more than one match is possible, any match is acceptable.

  • match_not_null: do not treat an empty sequence as a match.

  • match_continuous: do not search for matches other than at the beginning of the target sequence.

  • match_prev_avail: when an algorithm is called with a target sequence defined by a pair of iterators first and last, --first is a valid iterator; ignore match_not_bol and match_not_bow.

These flag values can be passed to the algorithms regex_match, regex_search, and regex_replace[1] to change the matching rules.

[1] Discussed in Chapter 20.

17.4.1. The match_default Flag

The flag designates the default matching rules for the grammar that was used to create the regular expression object used for the search. All of the search algorithms have a default value of match_default for their flags argument, so you often won't have to pass this flag to the algorithms.[2]

[2] Technically, match_default is required to have a value of 0, so it can be combined with any of the other flags without changing their meanings.

17.4.2. The match_not_bol Flag

Ordinarily, the beginning of the target sequence is treated as the beginning of a line. This flag tells the search engine not to apply this rule. That's useful in repetitive searches that resume where the previous search finished. We look at repetitive searches in Chapter 19. In the meantime, this example shows how this flag works.

Example 17.5. Flag match_not_bol (regexsrch/notbol.cpp)

#include <regex>
#include <iostream>
using std::tr1::regex; using std::tr1::regex_match;
using namespace std::tr1::regex_constants;
using std::cout;

int main()
  { // demonstrate use of match_not_bol
  regex rgx("^abcd");
  const char *tgt = "abcd";
  if (regex_match(tgt, rgx))
    cout << "Matches .\n";
  else
    cout << "Doesn' t match .\n";
  if (regex_match (tgt, rgx, match_not_bol))
    cout << "Matches .\n";
  else
    cout << "Doesn' t match .\n";
  return 0;
  }

The first search succeeds because the beginning of the target sequence is treated as the beginning of a line, thus matching the initial character '^'. The second search fails because the beginning of the target sequence is not treated as the beginning of a line.

17.4.3. The match_not_eol Flag

Ordinarily, the end of the target sequence is treated as the end of a line. This flag tells the search engine not to apply this rule. That's useful when searching through buffered input, where additional input might not yet have been read into the buffer.

Example 17.6. Flag match_not_eol (regexsrch/noteol.cpp)

#include <regex>
#include <iostream>
using std::tr1::regex; using std::tr1::regex_match;
using namespace std::tr1::regex_constants;
using std::cout;

int main()
  { // demonstrate use of match_not_eol
  regex rgx ("abcd$");
  const char *txt = "abcde";
  const char *end = txt + 4;        // points to 'e'
  if (regex_match(txt, end, rgx))
    cout << "Matches .\n";
  else
    cout << "Doesn' t match .\n";
  if (regex_match (txt, end, rgx, match_not_eol))
    cout << "Matches .\n";
  else
    cout << "Doesn't match .\n";
  return 0;
  }

The first search succeeds because the end of the target sequence is treated as the end of a line, thus matching the final character '$'. The second search fails because the end of the target sequence is not treated as the end of a line.

17.4.4. The match_not_bow Flag

Ordinarily, the beginning of the target sequence is treated as the beginning of a word if the first character can be part of a word. This flag tells the search engine not to apply this rule. That's useful in repetitive searches that resume where the previous search finished. We look at repetitive searches in Chapter 19. In the meantime, this example shows how this flag works.

Example 17.7. Flag match_not_bow (regexsrch/notbow.cpp)

#include <regex>
#include <iostream>
using std::tr1::regex; using std::tr1::regex_match;
using namespace std::tr1::regex_constants;
using std::cout;

int main()
  { // demonstrate use of match_not_bow
  regex rgx ("\\ babcd");
  const char *tgt = "abcd";
  if (regex_match (tgt, rgx))
    cout << "Matches .\n";
  else
    cout << "Doesn 't match .\n";
  if (regex_match (tgt, rgx, match_not_bow))
    cout << "Matches .\n";
  else
    cout << "Doesn' t match .\n";
  return 0;
  }

The first search succeeds because the beginning of the target sequence is treated as the beginning of a word, thus matching the initial escape sequence "\b". The second search fails because the beginning of the target sequence is not treated as the beginning of a word.

17.4.5. The match_not_eow Flag

Ordinarily, the end of the target sequence is treated as the end of a word if the last character can be part of a word. This flag tells the search engine not to apply this rule. That's useful when searching through buffered input, where additional input might not yet have been read into the buffer.

Example 17.8. Flag match_not_eow (regexsrch/noteow.cpp)

#include <regex>
#include <iostream>
using std::tr1::regex; using std::tr1::regex_match;
using namespace std::tr1::regex_constants;
using std::cout;

int main()
  { // demonstrate use of match_not_eow
  regex rgx ("abcd \\ b");
  const char *txt = "abcde";
  const char *end = txt + 4;        // points to 'e'
  if (regex_match (txt, end, rgx))
    cout << "Matches .\n";
  else
    cout << "Doesn' t match .\n";
  if (regex_match (txt, end, rgx, match_not_eow))
    cout << "Matches .\n";
  else
    cout << "Doesn' t match .\n";
  return 0;
  }

The first search succeeds because the end of the target sequence is treated as the end of a word, thus matching the final escape sequence "\b". The second search fails because the end of the target sequence is not treated as the end of a word.

17.4.6. The match_any Flag

For grammars other than ECMAScript, when a regular expression includes an alternation, a successful match should use the longest possible alternative. For example, when matching the regular expression "(wee|week).*" to the target sequence "weeknights", a successful match will associate the text "week" with the first capture group, because that's a longer match than "wee". This means that even after finding that the first alternative, "wee", leads to a successful match, the search engine must continue, in order to find the match that uses the longer alternative. This flag tells the search engine not to apply that rule. Any successful match is acceptable, even if a longer branch of an alternative would lead to a match with the same overall length.

This flag does not affect the requirement of finding the longest possible match. It simplifies the rule for breaking ties among equally long matches, by not requiring repeated searches for the longest leftmost alternative. We look at examples using this flag in Chapter 18.

17.4.7. The match_not_null Flag

This flag tells the search engine not to consider a match that matches zero characters. That's useful in repetitive searches that resume where the previous search left off. If the previous search matched zero characters, it left off at the place where it started, and repeating the search would simply find the zero-length match again. In order to make progress, a repetitive search should use the match_not_null flag after a zero-length match. We look at repetitive searches in Chapter 19. In the meantime, this example shows how this flag works.

Example 17.9. Flag match_not_null (regexsrch/notnull.cpp)

#include <regex>
#include <iostream>
using std::tr1::regex; using std::tr1::regex_match;
using namespace std::tr1::regex_constants;
using std::cout;

int main()
  { // demonstrate use of match_not_null
  regex rgx ("a *| b");
  const char *tgt = "ccc";
  if (regex_search (tgt, rgx))
    cout << "Matches .\n";
  else
    cout << "Doesn' t match .\n";
  if (regex_search (tgt, rgx, match_not_null))
    cout << "Matches .\n";
  else
    cout << "Doesn' t match .\n";
  return 0;
  }

In the first call to regex_search, the first alternative in the regular expression, "a*", successfully matches zero characters at the start of the target sequence. When the search is repeated with the match_not_null flag, it fails because this match is not allowed.

17.4.8. The match_continuous Flag

This flag tells the search engine to consider only matches beginning at the start of the target sequence. This doesn't affect the result of calling regex_match, which matches the entire target sequence. This flag can change the result of calling regex_search.

Example 17.10. Flag match_continuous (regexsrch/continuous.cpp)

#include <regex>
#include <iostream>
using std::tr1::regex; using std::tr1::regex_search;
using namespace std::tr1::regex_constants;
using std::cout;

int main()
  { // demonstrate use of match_continuous
  regex rgx ("bcd");
  const char *tgt = "abcd";
  if (regex_search (tgt, rgx))
    cout << "Matches .\n";
  else
    cout << "Doesn' t match .\n";
  if (regex_search (tgt, rgx, match_continuous))
    cout << "Matches .\n";
  else
    cout << "Doesn' t match .\n";
  return 0;
  }

The first search succeeds because the regular expression "bcd" matches the end of the target sequence. The second search fails because the match is required to begin at the beginning of the target sequence.

17.4.9. The match_prev_avail Flag

When passed to a search that uses a pair of iterators to designate the target sequence, this flag tells the search engine that the position preceding the first iterator is a valid element. This is needed when a search begins after the beginning of a sequence, so that the special rules for the first character in the target sequence won't be applied.

Example 17.11. Flag match_prev_avail (regexsrch/prevavail.cpp)

#include <regex>
#include <iostream>
using std::tr1::regex; using std::tr1::regex_match;
using namespace std::tr1::regex_constants;
using std::cout;
int main()
  { // demonstrate use of match_prev_avail
  regex rgx ("\\ bbcd");
  const char *txt = "abcd";
  const char *tgt = txt + 1;
  if (regex_match (tgt, rgx))
    cout << "Matches .\n";
  else
    cout << "Doesn' t match .\n";
  if ( regex_match (tgt, rgx, match_prev_avail))
    cout << "Matches .\n";
  else
    cout << "Doesn' t match .\n";
  return 0;
  }

The first match succeeds because the search engine treats the character 'b' in the target sequence as the beginning of a word. The second match fails because the search engine looks back one character and sees that the character 'b' in the target sequence is not the beginning of a word.


Exercises

Exercise 1

For each of the following errors, write a simple test case containing the error, and try to compile it. In the error messages, look for the key words that relate to the error in the code.

  1. Calling regex_match with a pointer to a null-terminated character sequence with a character type that's different from the element type used to define the regular expression object

  2. Calling regex_match with a basic_string object holding a character type that's different from the element type used to define the regular expression object

  3. Calling regex_match with a pair of iterators of type Iter, where the element type used to define the regular expression object is different from iterator_traits<Iter>::value_type

  4. Calling regex_match with a pair of forward iterators

Exercise 2

The regular expression "http://([^/:]+)(:(\d+))?(/.*)?" can be used to recognize an HTTP hostname.[3]

[3] This one is somewhat limited. For a good discussion of the problems involved in recognizing hostnames, see [Fri02].

  1. Write a program that uses regex_match to check each of the following character sequences to see whether the entire sequence is a valid HTTP hostname.

    1. "www.petebecker.com"

    2. "http://www.petebecker.com"

    3. "Answers are at http://www.petebecker.com:80."

    4. "http://www.petebecker.com has the answers."

  2. Write a program that uses regex_search to check each of the preceding character sequences to see whether the entire sequence is a valid HTTP hostname.

  3. Write a program that uses regex_search to check each of the preceding character sequences to see whether the sequence contains a valid HTTP hostname.

  4. Write a program that uses regex_match to check each of the preceding character sequences to see whether the sequence contains a valid HTTP hostname.

Exercise 3

The UNIX utility egrep searches files for occurrences of text that match a regular expression. Try your hand at implementing some of its options.

  1. Write a program that takes two arguments from the command line and treats the first argument as a regular expression and the second as the name of a file. The program should search through the named file, writing out each line that contains text that matches the regular expression.

  2. Change the program so that it writes out lines that do not contain text that matches the regular expression.

  3. Change the program so that, instead of writing out each line that has a match, it counts them and writes out the number of matched lines when it finishes.

  4. Change the program so that it writes out only lines in which the regular expression matches a complete word.

  5. Change the program to make the match case insensitive.

Exercise 4

Suppose that you have an application that writes a log file where each line is in one of three forms. Successful operations are logged in a line beginning with the word success, followed by a description of what was done. Failures are logged in one of two forms. Some failures are logged with the word error, followed by a space, followed by a one-, two-, or three-digit decimal error code. Other failures are logged with a generic message beginning with the word error, followed by a space, followed by ordinary text describing the error; this text will never begin with a digit. Write a program that scans the log file, looking for error messages with error codes, and reports the number of messages for each error code that it encountered. You don't need to parse the error message to do this; simply count the number of times each matching text sequence occurs.

Exercise 5

Suppose that you need to summarize all the error messages in a log file that was written in the format given in the previous example. That is, the program should determine how many error messages had each error code and how many had no error code. You can reuse most of the previous program for this exercise. If the test from the previous program fails but the text line begins with error the line is a generic error message. Add a test after the one that recognizes error codes to check for generic error messages, and count them separately. Make sure that the program handles such lines as "success, no error detected" correctly.

Exercise 6

The code for the previous exercise tests for the leading string error twice. That's annoying and often inefficient. Rewrite the code to check first for the leading text error, then for an error code, and classify the message accordingly.


Chapter 18. Search Results

Shun those studies in which the work that results dies with the worker.

The Notebooks
LEONARDO DA VINCI

Suppose that you want to scan a text file encoded in HTML and extract all the code snippets. Each snippet begins with "<CODE>" and ends with "</CODE>". The two markers are not case sensitive. In Chapter 17, we looked at a regular expression to recognize these snippets:

const char *expr = "<CODE>";

Now we need to enhance that expression, to require both markers, and to capture the text between the two markers. To do that, we add the second marker and a capture group to hold the text between the markers:

const char *expr = "<CODE>(.*)</CODE>";

After a successful match, the capture group will hold the text that was found between the two markers. To look at that text, we need to pass a match_results object to regex_search. If it finds a match, regex_search fills in the match_results object with details of the capture groups. The template match_results has a member operator[](size_type n) that returns a reference to a sub_match object, which, in turn, holds the information about the nth capture group. In this case, we're interested in the first capture group, so after the search, we need to look at match[1].

Example 18.1. Searching for Code Snippets (regexres/snippets.cpp)

#include <regex>
#include <iostream>
#include <fstream>
#include <string>
#include <stdlib.h>
using std::tr1::regex; using std::tr1::regex_search;
using std::tr1::smatch;
using std::string; using std::ifstream; using std::cout;

static void show_matches(const char *fname)
  { // scan file named by fname, line by line
  ifstream input(fname);
  string str;
  smatch match;
  const char *expr = "<CODE>(.*)</CODE>";
  regex rgx(expr,regex::icase);
  while (getline(input,str))
    { // check line for match
    if (regex_search(str,match,rgx))
      cout << match[1] << '\n';
    }
  }

int main(int argc,char *argv[])
  { // search for code snippets in text file
  if (argc != 2)
    { // wrong number of arguments
    cout << "Usage: snippets <filename>\n";
    return EXIT_FAILURE;
    }
  try
    { // search the file
    show_matches(argv[1]);
    }
  catch(...)
    { // something went wrong
    cout << "Error\n";
    return EXIT_FAILURE;
    }
  return 0;
  }

This code works because the two sets of search functions discussed in Chapter 17 have additional overloads that provide more detailed information about the range of characters in the target sequence that matched the regular expression and the ranges of characters that matched capture groups in the regular expression. To get this additional information, you pass a match_results object to any of the versions of regex_match or regex_search immediately before the regular expression object.


Section 18.1. Header <regex> Partial Synopsis

18.1. Header <regex> Partial Synopsis

In this chapter we look at the details of the class template sub_match, which identifies a matching subsequence, and the class template match_results, which holds a set of sub_match objects that, together, identify all matching subsequences from a search. Then we look again at the function templates regex_match and regex_search to see how to use match_results objects with them. In particular, we look at the following new components of the header <regex>:

    // CLASS TEMPLATE sub_match
template<class BidIt>
    class sub_match;
typedef sub_match<const char*> csub_match;
typedef sub_match<const wchar_t*> wcsub_match;
typedef sub_match<string::const_iterator> ssub_match;
typedef sub_match<wstring::const_iterator> wssub_match;

    // COMPARISON OPERATORS FOR sub_match
template<class BidIt>
    bool operator==(
      const   sub_match<BidIt>&,   const   sub_match<BidIt>&);
    // also operator!=, operator<, operator<=, operator>, operator>=

template<class    BidIt,    class    IOtraits,    class    Alloc>
    bool operator==(various types, const sub_match<BidIt>&);
    // also operator!=, operator<, operator<=, operator>, operator>=

template<class    BidIt,    class    IOtraits,    class    Alloc>
    bool operator==(const sub_match<BidIt>&, various types);
    // also operator!=, operator<, operator<=, operator>, operator>=

    // CLASS TEMPLATE match_results
template <class BidIt,
    class Alloc = allocator <sub_match<BidIt> >
    class match_results;
typedef match_results<const char*> cmatch;
typedef match_results<const wchar_t*> wcmatch;
typedef match_results<string::const_iterator> smatch;
typedef match_results<wstring::const_iterator> wsmatch;

    // FUNCTION TEMPLATE swap FOR match_results
template <class Elem, class IOtraits,
  class BidIt,class Alloc>
    void swap(match_results<BidIt,Alloc>& left,
        match_results<BidIt, Alloc>& right) throw();

    // COMPARISON OPERATORS FOR match_results
template<class    BidIt,   class    Alloc>
    bool operator==(const match_results<BidIt,Alloc>&,
        const match_results<BidIt, Alloc>&);
template<class    BidIt,   class    Alloc>
    bool operator!=(const match_results<BidIt, Alloc>&,
        const match_results<BidIt,  Alloc>&);

} }


Section 18.2. The sub_match Class Template

18.2. The sub_match Class Template

A sub_match object holds a Boolean value named matched that is true if the sub_match object points to a character sequence that was part of a successful match. In that case, its two iterator members, first and second, point to the beginning of the sequence and one past the end of the sequence, respectively. That is, given a sub_match object sub, if sub.matched is true, the half-open sequence [sub.first, sub.second) delimits the matching character sequence. Your code can create sub_match objects, but ordinarily, you'll use the ones contained in a match_results object.

template<class BidIt>
  class sub_match : public std::pair<BidIt,BidIt>{
public:
  bool matched;

difference_type length() const;
basic_string <value_type> str() const;
operator basic_string<value_type>() const;

int compare(const sub_match& right) const;
int compare(const basic_string<value_type>& right) const;
int compare(const value_type *right) const;

typedef BidIt iterator;
typedef typename iterator_traits<BidIt>::value_type
  value_type;
typedef typename iterator_traits<BidIt>::difference_type
  difference_type;
};

The template argument BidIt must be a type that meets the requirements for a bidirectional iterator. Ordinarily, this argument comes from the template match_results that holds the sub_match objects, so as long as you provide a bidirectional iterator type to match_results, this requirement will be satisfied.

The class template sub_match<BidIt> is derived from std::pair<BidIt, BidIt>. This base class provides the two members, first and second, that hold the two iterator values. The class template also has a Boolean member, matched, that holds true if the iterators point to a character sequence that was part of a successful match. That sequence can be emptythat is, first and second are equalfor a zero-length match. The sequence will also be empty if the corresponding capture group was not part of a successful match. In this case, the member matched will hold the value false, and the members first and second will point to the end of the target sequence.

A zero-length match can occur when a capture group consists solely of an assertion or of a repetition that allows zero repeats. For example:

  • "^" matches the target sequence "". The sub_match object that designates the full match holds two iterators that both point to the first position in the target sequence, and its member matched holds true.

  • "a(b*)a" matches the target sequence "aa". The sub_match object that designates the capture group holds iterators that both point to the second character in the target sequence, and its member matched holds TRue.

  • "(a)|b" matches the target sequence "b". The capture group is not part of the match. The sub_match object that designates the capture group holds iterators that point to the end of the target sequenceand thus compare equaland its member matched holds false.

Several of the member functions of sub_match<BidIt> take arguments or return objects of type basic_string<value_type>. As we'll see, value_-type is a typedef for the character type that the iterators point to. So basic_string<value_type> is a basic_string object that holds characters. When the text you're searching consists of ordinary char objects, basic_-string<value_type> is basic_string<char>, or, more simply, string.

18.2.1. Nested Types

typedef BidIt iterator;
typedef typename iterator_traits<BidIt>::value_type
  value_type;
typedef typename iterator_traits<BidIt>::difference_type
  difference_type;

The first type is a synonym for the first template type argument. The second and third types are synonyms for the iterator type's associated value_type and difference_type, respectively.

These type names can be convenient when you need to peer into the contents of the matching text. The type name iterator names the type of the iterators that the sub_match type holds; value_type is the character type that the iterators point to; and difference_type can hold the difference between two iterator values. For example:

typedef std::tr1::sub_match<const char*> cmatch;
cmatch::iterator iter;       // iter has type const char*
cmatch::value_type ch;       // ch has type char
cmatch::difference_type d;    // d has type std::ptrdiff_t

18.2.2. Access

bool matched;
BidIt first;      // inherited from pair
BidIt second;     // inherited from pair

If the capture group corresponding to the sub_match object was part of a successful match, the member matched holds true, and the members first and second designate the character range in the target sequence that matched the capture group. If the capture group was not part of a successful match, the member matched holds false, and the members first and last point to the end of the target sequence.

A newly constructed sub_match object has not been part of a successful match, so its matched member will hold false. As we'll see later, a call to a search algorithm that doesn't find a match leaves the sub_match objects in a match_-results object in an unspecified state, so you cannot count on any particular pattern of values when a search fails. If a search succeeds, the member matched in each sub_match object that was part of the match holds TRue, and the member matched in each sub_match object that was not part of the match holds false.

Example 18.2. Objects of type sub_match (regexres/subobjects.cpp)

#include <regex>
#include <algorithm>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <string>
using std::tr1::regex; using std::tr1::regex_match;
using std::tr1::match_results; using std::tr1::sub_match;
using std::copy;
using std::ostream_iterator; using std::string;
using std::cout;using std::setw;

template <class BidIt>
void show(const char *title,const sub_match <BidIt>& sm)
  {
  typedef sub_match<BidIt>::value_type MyTy;
  cout << setw(20) << title << ": ";
  if (sm.matched)
    copy(sm.first , sm.second,
      ostream_iterator<MyTy>(cout));
  else
    cout << "[no match]";
  cout << '\n';
  }

int main()
  {
  regex rgx("(a+)|(b+)");
  string tgt("bbb");
  match_results<string::iterator> match;
  show("no search" , match[0]);
  if (!regex_match(tgt.begin(), tgt.end(), match, rgx))
    cout << "search failed\n";
  else
    { // search succeeded, capture group 1 not part of match
    show("full match" , match[0]);
    show("capture group 1", m[1]);
    show("capture group 2", m[2]);
    }
  return 0;
  }

In this example, the expression match[0] returns a reference to the sub_-match object that represents the full match, and match[1] and match[2] return references to the sub_match objects that represent the subsequences that matched the first and second capture groups, respectively.

difference_type length() const;

The member function returns 0 if the member matched holds false; otherwise, distance(first, second).

This function returns the number of characters in the matching sequence delimited by [first, second) and returns 0 if the corresponding capture group was not part of the match. The function also returns 0 for a zero-length match, so don't use this return value to distinguish between those two cases. Use the member matched.

basic_string<value_type> str() const;
operator basic_string<value_type>() const;

The first member function returns an empty string object if matched holds false; otherwise, it returns basic_string<value_type>(first, second). The second member function returns str().

These member functions convert the matching sequence into a basic_string object. This will often be more convenient than using the raw iterators first and second. Here's the previous example, with the function show rewritten to use str().

Example 18.3. String Conversions (regexres/strings.cpp)

#include <regex>
#include <iomanip>
#include <iostream>
#include <string>
using std::tr1::regex; using std::tr1::regex_match;
using std::tr1::match_results; using std::tr1::sub_match;
using std::string;
using std::cout; using std::setw;

template <class BidIt>
void show(const char *title,const sub_match<BidIt>& sm)
  {
  cout << setw(20) << title << ":";
  if (sm.matched)
    cout << sm.str() << '\n';
  else
    cout << "[no match]\n";
  }

int main()
  {
  regex rgx("(a+)|(b+)");
  string tgt("bbb");
  match_results<string::iterator> m;
  show("no search", m[0]);
  if (!regex_match(tgt.begin() ,  tgt . end() , m ,  rgx))
    cout << "search failed\n";
  else
    { // search succeeded, capture group 1 not part of match
    show("full match", m[0]);
    show("capture group 1", m[1]);
    show("capture group 2", m[2]);
    }
  return 0;
  }

18.2.3. Comparison

Member Functions
int compare(const sub_match& right) const;
int compare(const basic_string<value_type>& right) const;
int compare(const value_type *right) const;

The first member function returns str().compare(right.str()). The second and third member functions return str().compare(right).

That is, these functions do a lexicographical comparison of the matched sequence and their argument,[1] returning a negative value if the matched sequence comes before the argument, zero if they are equal, and a positive value if the matched sequence comes after the argument.

[1] Technically, this comparison requires converting the sub_match object to a basic_string object, then calling its compare member function. That's a fairly expensive operation, which can usually be skipped. For sequences of characters of type char and wchar_t, the corresponding string types are basic_string<char> and basic_string<wchar_t>. Portable code can't tell, in these cases, whether the conversion to string was done, so under the as-if rule, the implementation doesn't have to do the conversion so long as it returns the right answer. For user-defined character types, the conversion is necessary because users are allowed to specialize basic_string for user-defined types. Such a specialization could make notes about whether it was used, so the as-if rule can't be used to eliminate the conversion.

Example 18.4. The compare Member Functions (regexres/compare.cpp)

#include <regex>
#include <iostream>
using std::tr1::regex; using std::tr1::regex_match;
using std::tr1::csub_match; using std::tr1::cmatch;
using std::cout;

static char *blocked_sites[] =
{ // block list; any resemblance between the names here
  // and real URLs is probably accidental
"www.idontwantmykidshere.com",
"www.lotsofxxxstuff.com",
"www.nra.org"
};
const int nsites = sizeof(blocked_sites)
  / sizeof(*blocked_sites);

bool allow(const csub_match& match)
  { // return false if match is on the blocked list
  for (int i = 0; i < nsites; ++i)
    if (match.compare(blocked_sites[i]) == 0)
      return false;
  return true;
  }

bool check_url(const char *url)
  { // return false if URL is not a valid HTTP URL or
    // if the hostname is on the blocked list
  regex rgx("http://([^/: ]+)(:(\\d+))?(/.*)?");
  cmatch match;
  return regex_match(url , match , rgx) && allow(match[1]);
  }

void connect(const char *url)
  { // connect to valid, unblocked URL
  if (check_url(url))
    {
    cout << "Okay to connect: " << url << '\n';
    // remainder of connection code left as exercise for the reader
    }
  else
    cout << "Invalid or blocked URL: "  << url << '\n';
  }

int main()
  { // connect to a couple of sites
  connect("http://www.xxx.com/risque/index.html");
  connect("http://www.petebecker.com/tr1book");
  connect("http:/invalid , for many reasons");
  return 0;
  }

In this example, I simplified the code by using some of the built-in typedefs instead of using the full names of the template instantiations. We'll look at these typedefs later. For now, cmatch is a synonym for match_results<const char*>, which is the appropriate type to hold the results of a search through an array of char. An object of type cmatch, in turn, holds objects of type sub_match<const char*>; the synonym for that one is csub_match.

The function allow does a linear search of the list of blocked URLs, to see whether the hostname passed to it is on the list. The function check_url checks whether its argument is a valid HTTP URL, and, if so, extracts the hostname and calls allow.[2]

[2] That rather hairy regular expression is taken from [Fri02], which explains its limitations and discusses possible improvements.

Nonmember Operators
template<class BidIt>
    bool operator==(const sub_match<BidIt>& left,
      const sub_match<BidIt>& right);

    // also operator!=, operator<, operator<=, operator>, operator>=
template<class BidIt /* maybe more */>
    bool operator==(
      various types left, const sub_match<BidIt>& right);
    // also operator!=, operator<, operator<=, operator>, operator>=
template<class BidIt /* maybe more */>
    bool operator==(
      const sub_match<BidIt>& left, various types right);
    // also operator!=, operator<, operator<=, operator>, operator>=

Each function template operator== returns true only if the argument left designates the same characters, in the same order, as the argument right.

Each function template operator!=(left, right) returns !(left == right).

Each function template operator< returns TRue only if the argument left designates a sequence of characters that lexicographically precedes the sequence of characters designated by the argument right.

Each function template operator<=(left, right) returns !(right < left).

Each function template operator>(left, right) returns right < left.

Each function template operator>=(left, right) returns !(left < right).

In addition to the overloaded member functions named compare, there's along list of operators for comparing sub_match objects to various representations of character sequences. Rather than list all six comparison operators for each pair of types,[3] the preceding synopsis gives the declaration for operator==. The remaining five operators are all declared in the obvious way.

[3] If you want to see the full list, it's in Appendix A.1.

The argument types referred to as various types can be any of the following, where Ty is iterator_traits<BidIt>::value_type:

  • An object of type basic_string<Ty, Traits, Alloc>

  • A pointer of type Ty*

  • A reference to type Ty

That is, you can compare a sub_match<BidIt> object to another sub_-match<BidIt> object, to a basic_string object that holds the same character type, to a null-terminated character string, and to a single character. Of course, the sub_match<BidIt> object can be on either side of the comparison.

Example 18.5. Comparison Operators (regexres/operators.cpp)

#include <regex>
#include <iostream>
using std::tr1::regex; using std::tr1::regex_match;
using std::tr1::csub_match; using std::tr1::cmatch;
using std::cout;

static char *blocked_sites[] =
{ // block list; any resemblance between the names here
  // and real URLs is probably accidental
"www.idontwantmykidshere.com",
"www.lotsofxxxstuff.com",
"www.nra.org"
};
const int nsites = sizeof(blocked_sites)
  / sizeof(*blocked_sites);

bool allow(const csub_match& match)
  { // return false if match is on the blocked list
  for (int i = 0; i < nsites; ++i)
    if (match == blocked_sites[i])
      return false;
    else if (match < blocked_sites[i])
      return true;
  return true;
  }

bool check_url(const char *url)
  { // return false if URL is not a valid HTTP URL or
    // if the hostname is on the blocked list
  regex rgx("http://([^/:]+)(:(\\d+))?(/.*)?");
  cmatch match;
  return regex_match(url , match , rgx) && allow(match[1]);
  }

void connect(const char *url)
  { // connect to valid, unblocked URL
  if (check_url(url))
    {
    cout << "Okay to connect: "<< url <<'\n';
    // remainder of connection code left as exercise for the reader
    }
  else
    cout << "Invalid or blocked URL: " << url << '\n';
  }

int main()
  { // connect to a couple of sites
  connect("http://www.xxx.com/risque/index.html");
  connect("http://www.petebecker.com/tr1book");
  connect("http:/invalid,for many reasons");
  return 0;
  }

This example is a lot like the previous one but with two differences, both in the function allow. First, this example uses operator== to check whether the hostname is in the blocked list. Second, this example uses operator< to take advantage of the list's being in alphabetical order to cut the linear search short when it reaches a name that comes after the target hostname.


Section 18.3. Predefined sub_match Types

18.3. Predefined sub_match Types

typedef sub_match<const char*> csub_match;
typedef sub_match<const wchar_t*> wcsub_match;
typedef sub_match<std::string::const_iterator> ssub_match;
typedef sub_match<std::wstring::const_iterator> wssub_match;

The four names are synonyms for the most commonly used sub_match types. Keep in mind that the template argument to sub_match must be the iterator type associated with the target text that was passed to regex_match or regex_search. When the target text was passed as a char* or wchar_-t* (const or otherwise), the associated iterator types are const char* and const wchar_t*, respectively. When the target text is held in a string or wstring object, the associated iterator type is the string type's nested name const_iterator.

Example 18.6. Predefined sub_match Types (regexres/predefined.cpp)

#include <regex>
#include <iostream>
#include <string>
using std::tr1::regex; using std::tr1::wregex;
using std::tr1::regex_match;
using std::tr1::cmatch; using std::tr1::smatch;
using std::tr1::wcmatch;using std::tr1::wsmatch;
using std::tr1::csub_match; using std::tr1::ssub_match;
using std::tr1::wcsub_match; using std::tr1::wssub_match;
using std::string; using std::wstring;
using std::cout;

static void show(...)
  { // called with unknown type
  cout << "Called with unknown argument type\n";
  }

static void show(csub_match match)
  { // called with csub match argument
  cout << "Called show(csub_match)\n";
  }

static void show(wcsub_match match)
  { // called with wcsub match argument
  cout << "Called show(wcsub_match)\n";
  }

static void show(ssub_match match)
  { // called with ssub match argument
  cout << "Called show(ssub_match)\n";
  }

static void show(wssub_match match)
  { // called with wssub match argument
  cout << "Called show(wssub_match)\n";
  }

int main()
  { // show sub match types for various match results types
  regex rgx("abc");
  cmatch match0;
  if (regex_match("abc", match0, rgx))
    show(match0[0]);
  smatch match1;
if (regex_match(string("abc"), match1, rgx))
  show(match1[0]);
wregex wrgx(L"abc");
wcmatch match2;
if (regex_match(L"abc", match2, wrgx))
  show(match2[0]);
wsmatch match3;
if (regex_match(wstring(L"abc"), match3, wrgx))
  show(match3[0]);
return 0;
}


Section 18.4. The match_results Class Template

18.4. The match_results Class Template

The class template match_results is a nonmodifiable container.[4] It holds the results of a successful match found by a call to regex_match or regex_-search. Typically, your code will create a match_results<BidIt> object, with the type BidIt being an iterator of the same type as the iterator for the target text. For example, when the target text is passed as a const char*, use match_results<const char *>. When the target text is passed as a standard string object, use match_results<string::const_iterator>.

[4] That is, it's not modifiable by ordinary code. The regular expression search functions that take a regex_match object, of course, modify its contents during a search.

template <class BidIt,
  class Alloc = allocator<
    typename iterator_traits<BidIt>:: value_type> >
   class match_results {
public:
  explicit match_results(const Alloc& alloc = Alloc());
  match_results (const match_results & right);

  match_results& operator=(const match_results& right);
  void swap(const match_results& other) throw();

  const_reference operator[](size_type sub) const;
  difference_type position(size_type sub = 0) const;
  difference_type length(size_type sub = 0) const;
  string_type str(size_type sub = 0) const;

  const_reference prefix() const;
  const_reference suffix() const;

  const_iterator begin() const;
  const_iterator end() const;
  template<class OutIt>
    OutIt format(OutIt out,
      const string_type& fmt,
      match_flag_type flags = format_default) const;
string_type format(const string_type& fmt,
  match_flag_type flags = format_default) const;

  size_type size() const;
  size_type max_size() const;
  bool empty() const;
  allocator_type get_allocator() const;

  typedef sub_match<BidIt> value_type;
  typedef const typename Alloc::const_reference
    const_reference;
  typedef const_reference reference;
  typedef T0 const_iterator;
  typedef const_iterator iterator;
  typedef typename iterator_traits<BidIt>::difference_type
    difference_type;
  typedef typename Alloc::size_type size_type;
  typedef Alloc allocator_type;
  typedef typename iterator_traits<BidIt>::value_type
    char_type;
  typedef basic_string<char_type> string_type;

  };

The template takes two type arguments. The first, listed here as BidIt, must be a bidirectional iterator, the same type as you're going to use to point to the target text. The second is an allocator type. An object of this type is stored in the match_results object and will be used to manage the memory needed to hold the various sub_match objects that hold the details of a successful match. The default allocator type is an instance of the allocator from the standard library.

Objects of type match_results<BidIt> can be created, copied, assigned, and swapped. These operations are discussed in Section 18.4.1. After a successful search, you can examine capture groups individually with the member functions position, length, str, and operator[], and you can look at the part of the target text that preceded or followed the matching text with the member functions prefix and suffix. These are discussed in Section 18.4.2. Because a match_results object is a container, you can call the member functions begin and end to get a pair of iterators that designate a half-open sequence of sub_match objects, as discussed in Section 18.4.3. You can also ask about the number of elements in the container, with the member functions size, max_size, and empty, and you can get a copy of the container's allocator with get_allocator. These functions are discussed in Section 18.4.4. Like all containers, the template defines several nested type names, described in Section 18.4.5. The library provides two operators to compare match_results<BidIt> objects for equality (Section 18.4.6) and four typedef names that provide synonyms for commonly used match_results instances (Section 18.4.7). Finally, two member functions can be used to produce formatted text by replacing various parts of the target text. These are discussed in Chapter 20, which covers formatting and text replacement.

18.4.1. Creating and Modifying match_results Objects

explicit match_results::match_results(
  const Alloc& alloc = Alloc());

The constructor constructs a match_results object that holds a copy of the argument alloc and no elements.

Thus, after constructing an object with this constructor, the member function size returns 0, and the member function str returns an empty string.

match_results::match_results(const match_results& right);
match_results& match_results::operator=(
  const match_results& right);

The copy constructor constructs an object that is a copy of its argument. The assignment operator replaces the object's controlled sequence with a copy of its argument.

void match_results::swap(
  const match_results& other) throw();
template<class Elem,class IOtraits,
class BidIt, class Alloc >
  void swap(match_results<BidIt , Alloc >& left,
      match_results<BidIt , Alloc>& right) throw()
      { // swap left and right
      left.swap(right);
      }

The member function swaps the object's controlled sequence with its argument's controlled sequence and does not throw exceptions. The non-member function calls left.swap(right).

Example 18.7. Constructors and Modifiers for match_results (regexres/modify.cpp)

#include <regex>
#include <iostream>
#include <stdlib.h>
using std::tr1::regex; using std::tr1::match_results;
using std::tr1::regex_search;
using std::cout;

typedef match_results<const char *> mtch;

static void show(const char *title, const mtch& match)
  { // summarize match results object
  cout << title << ":\n";
  cout << "size:" << match.size() << '\n';
  cout << "contents: `" << match.str() << "`\n";
  }

int main()
  { // demonstrate various constructors and modifiers
  mtch match;
  show("after default constructor" , match);
  regex rgx("b(c*)d");
  const char *tgt = "abcccde";
  mtch match1;
  if (!regex_search(tgt,match1,rgx))
    return EXIT_FAILURE;
  show("after successful search" , match1);
  mtch match2(match1);
  show("after copy construction" , match2);
  match.swap(match1);
  show("after swap" , match);
  swap(match , match1);
  show("after another swap" , match);
  match = match2;
  show("after assignment" , match);
  return 0;
  }

18.4.2. Examining Individual Matches

const_reference
  match_results::operator[](size_type n) const;

The operator returns a reference to the nth element in the controlled sequence or a reference to an empty sub_match object if size() <= n or if the nth capture group was not part of the match.

The 0th element of the controlled sequence is a sub_match object that delineates the entire text that matched the regular expression. Succeeding elements delineate the text that matched the corresponding capture group. If a capture group was not part of the match or if n is larger than the number of capture groups, the sub_match object is empty; these sub_match objects are not required to be distinct.

difference_type position(size_type n = 0) const;

The member function returns distance(prefix().first(), (*this)[n].first).

That is, it returns the offset of the beginning of the text that matches capture group n from the beginning of the target text.

difference_type length(size_type n = 0) const;

The member function returns (*this)[n].length().

That is, it returns the number of characters in the nth capture group.

string_type str(size_type n = 0) const;

The member function returns string_type((*this)[n]).

That is, it returns an object of type string_type that holds a copy of the text of the nth capture group.

const_reference match_results::prefix() const;
const_reference match_results::suffix() const;

The first member function returns a reference to an object of type sub_-match<BidIt> that points to the character sequence that begins at the start of the target sequence and ends at (*this)[0].first. The second member function returns a reference to an object of type sub_-match<BidIt> that points to the character sequence that begins at (*this)[size() - 1].second and ends at the end of the target sequence.

That is, the two member functions return sub_match objects that point to the text that precedes and follows, respectively, the text that matched the regular expression.

Example 18.8. Examining Contained Objects (regexres/examine.cpp)

#include <regex>
#include <iostream>
#include <stdlib.h>
using std::tr1::regex; using std::tr1::regex_search;
using std::tr1::match_results; using std::tr1::sub_match;
using std::cout;

typedef match_results<const char *> mtch;

static void show(int idx, const mtch& match)
  { // show contents of match[idx]
  cout << "match[" << idx << "]: "
    << (match[idx].matched  ?  "  "  : "not")
    << "matched, `" << match.str(idx)
    << "` at offset " << match.position(idx)
    << ", with length " << match.length(idx) << '\n';
  }

int main()
  { // demonstrate operator[]
  regex rgx("b(c*|(x))d");
  const char *tgt = "abcccde";
  mtch match;
  if (!regex_search(tgt, match, rgx))
    return EXIT_FAILURE;

  cout << "After search, size is "
    << match.size() << '\n';
  cout << "text preceding match is `"
    << match.prefix() << "`\n";
  for (int i = 0; i < match.size() + 2; ++i)
    show(i,match);
  cout << "text following match is `"
    << match.suffix() << "`\n";
  return 0;
  }

The output from this program shows that match holds three sub_match objects. The object returned by prefix() holds the text "a", which is the text that preceded the matching text. The object returned by suffix() holds the text "e", which is the text that followed the matching text. The object returned by match[0] holds the text "bcccd", which is all the target text that matched the regular expression. The object returned by match[1] holds the text "ccc", which is the part of the target text that matched the first capture group, "(c*|(x))". The object returned by match[2] is empty because capture group 2, "(x)", wasn't part of the match. The objects returned by match[3] and match[4] are also empty because they refer to capture groups that don't exist in the regular expression.

18.4.3. Iterating Through All Matches

const_iterator match_results::begin() const;
const_iterator match_results::end() const;

The first member function returns a random access iterator that points to the first element of the controlled sequence or just beyond the end of an empty sequence. The second member function returns a random access iterator that points just beyond the end of the controlled sequence.

Note that the controlled sequence is the sequence of sub_match objects returned by calling operator[] with successive values from 0 to size() - 1. It does not include the sub_match objects returned by prefix or suffix unless those happen to be equal to one of the other sub_match objects, which occurs only with empty sub_match objects.

Example 18.9. Iterating Through an Object (regexres/iterate.cpp)

#include <regex>
#include <iostream>
#include <algorithm>
#include <iterator>
using std::tr1::regex; using std::tr1::regex_search;
using std::tr1::match_results; using std::tr1::sub_match;
using std::cout; using std::ostream_iterator;
using std::copy;

typedef const char *iter;
typedef sub_match<iter> sub;
typedef match_results<iter> mtch;

namespace std { // add inserter to namespace std
template <class Elem,class Alloc>
basic_ostream<Elem, Alloc>& operator<<(
  basic_ostream<Elem, Alloc>& out, const sub & val)
  { // insert sub match <iter> into stream
  return out << '`' << val.str() << '`';
  }
}

int main()
  {
  regex rgx("b(c*|(x))d");
  const char *tgt = "abcccde";
  mtch match;
  if (!regex_search(tgt, match, rgx))
    return EXIT_FAILURE;
  copy(match.begin(), match.end(),
    ostream_iterator <sub>(cout, "\n"));
  return 0;
  }

18.4.4. General Queries

size_type match_results::size() const;
size_type match_results::max_size() const;
bool match_results::empty() const { return size() == 0;}

The first member function returns the length of the controlled sequence. The second member function returns the length of the longest sequence that the object can control. The third member function returns true only if the length of the controlled sequence is 0.

allocator_type match_results::get_allocator() const;

The member function returns a copy of the stored allocator object.

18.4.5. Nested Types

typedef sub_match <BidIt> value_type;
typedef const typename Alloc::const_reference
  const_reference;
typedef const_reference reference;
typedef T0 const_iterator;
typedef const_iterator iterator;
typedef typename iterator_traits<BidIt>::difference_type
  difference_type;
typedef typename Alloc::size_type size_type;
typedef Alloc allocator_type;
typedef typename iterator_traits<BidIt>::value_type
  char_type;
typedef basic_string<char_type> string_type;

The type names nested in match_results<BidIt, Alloc> are defined as follows:

  • value_type: a synonym for sub_match<BidIt>

  • const_reference: a description of an object that can serve as a reference to an unmodifiable element of the controlled sequence

  • reference: a description of an object that can serve as a reference to an unmodifiable element of the controlled sequence

  • const_iterator: a description of an object that can serve as a random-access iterator that points at unmodifiable elements of the controlled sequence

  • iterator: a description of an object that can serve as a random-access iterator that points at unmodifiable elements of the controlled sequence

  • difference_type: a synonym for iterator_traits<BidIt>::difference_type; it describes an object that can represent the difference between any two iterators that point at elements of the controlled sequence

  • size_type: a synonym for Alloc::size_type

  • allocator_type: a synonym for the template argument Alloc

  • char_type: a synonym for iterator_traits<BidIt>::value_type, which is the element type of the character sequence that was searched

  • string_type: a synonym for basic_string<char_type

A match_results object satisfies the requirements for a sequence container[5] except that operations that modify the sequence are not supported. All but the last two nested types are required for a sequence container. The last two make it easier to talk about the contents of the character sequences that the container holds.

[5] As defined in the C++ standard.

18.4.6. Comparing match_results Objects

template <class BidIt,class Alloc>
  bool operator==(
    const match_results<BidIt , Alloc>& left,
    const match_results<BidIt , Alloc>& right);
template <class BidIt , class Alloc>
  bool operator!=(
    const match_results<BidIt , Alloc>& left,
    const match_results<BidIt , Alloc>& right)
      { return !(left == right);}

The first operator returns TRue only if left.size() == right.size() and equal(left.begin(), left.end(), right.begin()). The second operator returns TRue only if !(left == right).

These operators apply the usual definition of equality for container types: Two containers are equal if they hold the same number of elements and corresponding elements are equal.

18.4.7. Predefined match_results Types

typedef match_results<const char *> cmatch;
typedef match_results<const wchar_t *> wcmatch;
typedef match_results<string::const_iterator> smatch;
typedef match_results<wstring::const_iterator> wsmatch;

The four names are synonyms for the most commonly used match_results types. Keep in mind that the template argument to match_results must be the iterator type associated with the target text that was passed to regex_-match or regex_search. When the target text is a pointer to char or wchar_t (const or otherwise), the associated iterator type is a pointer to const char or to const wchar_t. When the target text is a string or wstring object, the associated iterator type is the string type's nested name, const_iterator.

18.4.8. Formatting Text

template<class OutIt>
OutIt match_results::format(OutIt out,
  const string_type& fmt,
  match_flag_type flags = format_default) const;
string_type match_results::format(
  const string_type& fmt,
  match_flag_type flags = format_default) const;

These member functions are discussed in the Chapter 20, which covers formatting and text replacement.


Exercises

Exercise 1

For each of the following errors, write a simple test case containing the error, and try to compile it. In the error messages, look for the key words that relate to the error in the code.

  1. Attempting to modify the contents of a match_results object

  2. Attempting to specialize match_results with an iterator type that is not a bidirectional iterator or a random access iterator

  3. Attempting to call regex_search with a match_results specialization and a basic_regex object whose element types are not the same

Exercise 2

Write a utility function that takes a reference to a match_results object and shows whether that object was part of a successful match and, if so, shows useful information about the match: its prefix, the contents of each capture group, and its suffix. For each capture group that was part of the match, indent its text by the number of characters that preceded the capture group in the original text. Use this utility function to review any of the Chapter 15 examples that were unclear.

Exercise 3

Write a utility function that takes a reference to a match_results object and an index value and shows whether the sub_match object at that index value was part of a successful match and, if so, shows all the available information about the capture group that it matched: its position in the target text, its length, and its contents. Search for text matching the regular expression "(a(.*)b)|(c(.*)d)" in the target text "ab", and compare the information about capture groups 2 and 4. Make sure that you understand the difference between them.

Exercise 4

One of the differences between the ECMAScript grammar and the UNIX-based grammars is the UNIX requirement to find the longest sub-matches while finding the longest overall match. Write a program that searches for text matching the regular expression "(wee|week).*" in the target text "weeknights", using both the ECMAScript and the ere grammars, and shows the contents of capture group 1. Also try it with ere and the flag match_any.


Chapter 19. Repetitive Searches

There are only two or three human stories, and they go on repeating themselves as fiercely as if they had never happened before.

O Pioneers!
WILLA CATHER

Did you spot the problem with the example program that searched for code snippets in a text file at the beginning of Chapter 18? In lines that have multiple code snippets, everything between the first "<CODE>" and the last "</CODE>" is listed as a single snippet. To separate multiple snippets, we first have to change the regular expression a bit so that it doesn't swallow multiple snippets. In this case, we can replace the ".*" with a nongreedy repetition:

string expr = " <CODE>(.*?) </CODE>";

Now, to resume searching after the text that matched, we have to change the code. To do that, instead of searching the entire line from the file, we use a pair of iterators that point at the contents of the line. After a match, we advance the first iterator to point at the character immediately following the match and search again.

Example 19.1. Repeated Searches (regexiter/repeated.cpp)

#include <regex>
#include <iostream>
#include <fstream>
#include <string>
#include <stdlib.h>
using std::tr1::regex; using std::tr1::regex_search;
using std::tr1::smatch;
using std::string; using std::ifstream; using std::cout;

static void show_matches (const char *fname)
  { //scan file named by fname, line by line
  ifstream input (fname);
  string str;
  smatch match;
  string expr = "<CODE>(.*?) </CODE>";
     regex rgx (expr, regex::icase);
     while (getline (input, str))
       { // check line for match
       string::const_iterator first = str.begin ();
       string::const_iterator second = str.end ();
       while (regex_search (first, second, match, rgx))
       { // show match, then skip past it
         cout << match[1]<< '\n';
         first += match.position () + match.length ();
         }
       }
     }

int main(int argc, char  *argv[])
  { // search for code snippets in text file
  if (argc != 2)
    { // wrong number of arguments
    cout << "Usage : snippets <filename>\n";
    return EXIT_FAILURE;
    }
  try
    { // search the file
    show_matches (argv [1]);
    }
  catch (...)
    { // something went wrong
    cout << "Error\n";
    return EXIT_FAILURE;
    }
  return 0;
  }

Don't be fooled, though: Repetitive searches aren't usually that easy to write. For example, if the regular expression begins with a "^", simply restarting the search after a match, as the previous example does, can lead to wrong answers. The following program searches the target text "abcdef" for subsequences that match the regular expression "^(abc|def)". The only one is the initial "abc", but the program finds two, reporting that "def" also matches.

Example 19.2. Naive Search Doesn't Work (regexiter/naive.cpp)

#include <regex>
#include <iostream>
#include <string>
using std::tr1::regex; using std::tr1::regex_search;
using std::tr1::smatch;
using std::string; using std::cout;

int main()
   { // search for regular expression in text
     string str = "abcdef";
     string::const_iterator first = str.begin ();
     string::const_iterator second = str.end ();
     smatch match;
     string expr = "^(abc | def)";
     regex rgx(code);
     while (regex_search(first, second, match, rgx))
      { // check range for match
        cout << match [0] << '\n';
        first+=match.position () + match.length ();
        }
     return 0;
     }

In this chapter, we look first at the complications that any repetitive search has to allow for and the techniques for fixing problems (Section 19.1). Then we look at prewritten solutions, in the form of the class template regex_iterator (Section 19.2) and the class template regex_token_iterator (Section 19.3).


Section 19.1. Brute-Force Searches

19.1. Brute-Force Searches

In Chapter 17 we looked at several flags that you can pass to the regular expression search functions to change the details of regular expression matching. Here, we look at some of those flags again but in the context of specific problems that arise in repetitive searches. Eventually, we'll build a search function that avoids these problems; you can judge for yourself whether that's a better approach than using the two forms of regular expression iterator that the TR1 library provides.

19.1.1. Lost Anchors

Earlier in this chapter, we looked at a naive search function that reported two matches when applying the regular expression "^(abc|def)" to the target text "abcdef". The problem with simply repeating the same search at a new location in the target text, as that program did, is that on the second call to regex_search, the target text is passed, effectively, as "def", which does match the regular expression. That is, we chopped off the start of the target text but didn't tell the search function that we had done that, so it matched the "^" at the beginning of the regular expression to the beginning of the text that we passed, even though the text was not the beginning of the target text. The solution to this problem is simply to tell the search function that we're not at the beginning of a line, so "^" shouldn't match. To do that, we use the flag match_not_bol for all searches except the first.

Example 19.3. Preserving Anchors (regexiter/search1.cpp)

#include <regex>
#include <iostream>
using std::tr1::regex; using std::tr1::cmatch;
using std::tr1::regex_search;
using namespace std::tr1::regex_constants;
using std::cout;

static void search (const char*tgt, const char *expr)
   { // show all subsequences of tgt that match expr
     regex rgx (expr);
     cmatch match;
     match_flag_type flags  =  match_default;
     const char*first  =  tgt;
     const char*last  =  tgt+strlen (tgt);
     for (;;)
     { // keep trying
       if (regex_search(first, last, match, rgx, flags))
           { // show match, move past it
           cout << match.str ()
              << "at offset"
              << (match [0].first-tgt) << '\n';
           first+=match.position ()+match.length ();
           flags = flags | match_not_bol;
           }
       else
           break;
       }
     }

int  main()
{ // demonstrate use of match_not_bol
const char*expr = "^(abc | def)";
const char*tgt = "abcdef";
search (tgt, expr);
return 0;
}

19.1.2. Lost Word Boundaries

The regular expression "\babc" should match the target text "abcabc" in one place: the first occurrence of the character sequence "abc". The second "abc" doesn't match, because it doesn't start at a word boundary. If you try the previous search function with this regular expression and target text, it will find two matches. The problem is similar to the one with lost anchors: When we restart the search after the first match, the regular expression engine treats the start of the text as a word boundary. You might be tempted to fix that with the same approach we used before, by adding the flag match_not_-bow after a successful match. But the two cases are different: A "^" can match only at the beginning of the original target text, so it's okay to simply disallow that match once we've moved away from the beginning of the text. A word boundary can occur inside the target text as well as at the beginning, so we have to be careful to disable matching the beginning of a word only when we're not at the beginning of a word. That can be done by checking whether the last character in a match can be in a word and, if so, prohibiting matching the beginning of a word on the next pass. That solves half the problem.

The other half of the problem occurs with a regular expression like "\b3", when matched against the target text "33". The first "3" is at a word boundary, so it should match. The second "3" is not at a word boundary, so it should not match. But the previous version of search will find that the second one matches because in the target text that's passed for the second search, it is at the beginning of the target text. So we also need to disable matching of the end of a word when the previous character cannot be in a word.

But there's an easier way. The regular expression engine already knows how to identify characters that can be in a word, so we don't need to write that logic ourselves. All we need to do is tell the engine that it can look at the character in front of the target text to decide whether it's at the beginning of a word. That's what the flag match_prev_avail does. Of course, we should do that only when we know that a valid character is in front of the target text. Once we've moved forward in the target text, we know that we can look behind the current position.

Example 19.4. Preserving Word Boundaries (regexiter/search2.cpp)

#include <regex>
#include <iostream>
using std::tr1::regex; using std::tr1::cmatch;
using std::tr1::regex_search;
using namespace std::tr1::regex_constants;
using std::cout;

static void search (const char*tgt, const char*expr)
     { // show all subsequences of tgt that match expr
     regex rgx (expr);
     cmatch match;
     match_flag_type flags =  match_default;
     const char*first = tgt;
     const char*last = tgt+strlen (tgt);
     for (;;)
    { // keep trying
      if (regex_search (first, last, match, rgx, flags))
      { // show match, move past it
        cout << match.str ()
          <<"at offset"
          << (match [0]. first - tgt) << '\n';
        first+=match.position ()+match.length ();
        flags = flags | match_not_bol | match_prev_avail;
        }
      else
        break;
      }
     }

int main()
  { //demonstrate use of match_not_bol
  const char*expr = "\\babc";
  const char*tgt = "abcabc";
  search (tgt, expr);
  return 0;
  }

19.1.3. Empty Matches

To understand the problem that empty matches pose, we first need to look at empty matches in more detail. The regular expression "a*" matches a sequence of zero or more repetitions of the character 'a'. When it matches zero characters, that's an empty match. If you call regex_search to see whether that regular expression matches the target text "bcd", the answer will be that it matches, right at the beginning.

Example 19.5. Empty Match (regexiter/empty.cpp)

#include <regex>
#include <iostream>
using std::tr1::regex; using std::tr1::cmatch;
using std::tr1::regex_search;
using namespace std::tr1::regex_constants;
using std::cout;

int main()
  { // show empty match
  const char*expr = "a*";
  regex rgx(expr);
  cmatch match;
  const char*tgt = "bcd";
  if (regex_search(tgt, match, rgx))
    { // show the match
    cout << "Matched at offset" <<  match.position ()
      << ",with length" << match.length () << '\n';
    }
  return 0;
  }

If we use the search function that we wrote to eliminate lost anchors to search for all occurrences of "a*" in the target text "bcd", we'll get into trouble. The first match is at offset 0, and its length is 0, so the function will adjust the position in the target string by zero characters and call regex_-search again. This will loop until you get bored and terminate the program.

There are two obvious solutions. First, move the position in the target text forward by one character when you get an empty match. Second, temporarily prohibit empty matches. Both work for some cases, but, as we'll see, you really need a combination of the two.

This version of search implements the first fix.

Example 19.6. Jumping Past Empty Matches (regexiter/search3.cpp)

#include <regex>
#include <iostream>
#include <string>
using std::tr1::regex; using std::tr1::cmatch;
using std::tr1::regex_search;
using namespace std::tr1::regex_constants;
using std::cout; using std::string;

static void search (const char*tgt, const char*expr)
   { // show all subsequences of tgt that match expr
     regex rgx(expr);
     cmatch match;
     match_flag_type flags = match_default;
     const char*first = tgt;
     const char*last = tgt+strlen(tgt);
     string empty("[empty]");
     for(;;)
   { // keep trying
     if(regex_search(first, last, match, rgx, flags))
      { // show match, move past it
        cout << (match.length()?match.str ():empty)
          << "at offset"
          << (match[0].first-tgt) << '\n';
        if (match.length()!=0)
          first+=match.position()+match.length();
        else if (first == last)
          break;
        else
          ++first;
        flags = flags| match_not_bol|match_prev_avail;
        }
     else
        break;
     }
     }

int main()
  { // demonstrate use of match_not_null
  const char*expr = "a*";
  const char*tgt = "bcd";
  search (tgt, expr);
  return 0;
  }

Note the test for first == last; without this, the function will increment first past the end of the target text if an empty match occurs at the end of the target text. This works fine for the regular expression "a*", but try it with the regular expression "a*|c". It doesn't see that the regular expression matches the "c" in the target text. That's because it finds the empty match at that position and jumps past it.

This version of search implements the second fix, using the flag match_-not_null to prevent empty matches until after the next successful match.

Example 19.7. Blocking Empty Matches (regexiter/search4.cpp)

#include <regex>
#include <iostream>
#include <string>
using std::tr1::regex; using std::tr1::cmatch;
using std::tr1::regex_search;
using namespace std::tr1:: regex_constants;
using std::cout; using std::string;

static void search(const char*tgt, const char*expr)
  { // show all subsequences of tgt that match expr
  regex rgx(expr);
  cmatch match;
  match_flag_type flags = match_default;
  match_flag_type mod = match_default;
  const char*first = tgt;
  const char*last = tgt+strlen(tgt);
  string empty("[empty]");
  for(;;)
    { // keep trying
    if (regex_search (first, last, match,
      rgx, flags| mod))
      { // show match, move past it
      cout << (match.length()? match.str():empty)
        << "at offset"
        << (match [0].first-tgt) << '\n';
      if (match.length()!=0)
        { // move past match, clear modifier flags
        first+=match.position()+match.length();
        mod =  match_default;
        }
      else
        mod = match_not_null;
      flags = flags | match_not_bol | match_prev_avail;
      }
    else
      break;
    }
  }

int main()
  { // demonstrate use of match_not_bol
  const char * expr = "a*|c";
  const char*tgt = "bcd";
  search(tgt, expr);
  return 0;
  }

This program does, indeed, find the match of "c", but it's not right, because it misses the empty match before "c". We've shut off empty matches for too long. The fix is to shut off empty matches only at the current position in the target text. To do that, we need two changes. First, we need to add the flag match_continuous, so that the regular expression search engine won't look for matches that occur after the start of the target text. That way, we control when the search advances further into the target text. Second, if that constrained search fails, we need to turn off the constraint and move to the next position in the target text. That is, we need to combine the two previous attempted solutions.

Example 19.8. Fixing an Empty Match (regexiter/search5.cpp)

#include <regex>
# include <iostream>
# include <string>
using std::tr1::regex; using std::tr1::cmatch;
using std::tr1::regex_search;
using namespace std::tr1::regex_constants;
using std::cout; using std::string;

static void search(const char*tgt, const char*expr)
  { // show all subsequences of tgt that match expr
  regex rgx(expr);
  cmatch match;
  match_flag_type flags = match_default;
  match_flag_type mod = match_default;
  const char*first = tgt;
  const char* ast = tgt+ strlen(tgt);
  string empty("[empty]");
  for(;;)
    { // keep trying
    if (regex_search(first, last, match,
      rgx, flags |   mod))
      { // show match, move past it
      cout << (match.length()? match.str():empty)
        << "at offset"
        << (match [0].first-tgt) << '\n';
      if (match.length()!=0)
        { // move past match, clear modifier flags
        first+=match.position()+ match.length();
        mod = match_default;
        }
      else
        mod = match_not_null | match_continuous;
      flags = flags | match_not_bol | match_prev_avail;
      }
    else if (mod != match_default && first!= last)
      { // move past failed match, clear modifier flags
      ++first;
      mod = match_default;
      }
    else
      break;
    }
  }

int main()
 { // demonstrate use of match_not_bol
  const char *expr = "a*|c";
  const char *tgt = "bcd";
  search(tgt, expr);
  return 0;
  }

Now we have a robust search function. It's a little difficult to reuse, [1] though, because the action that it performs when it finds a match is embedded in the code that finds the match. Although this code can be made more generic, in most cases, you should use one of the two forms of iterator that the TR1 library provides, rather than trying to adapt this explicit loop.

[1] That is, unless "reuse" means "cut and paste," as is often the case, for example, in Java.


Section 19.2. The regex_iterator Class Template

19.2. The regex_iterator Class Template

The class template regex_iterator is defined in the header <regex>.

namespace std {      // C++ standard library
 namespace tr1  {    // TR1 additions

    // CLASS TEMPLATE regex_iterator
template <class BidIt,
     class Elem = typename iterator_traits <BidIt>::value_type,
     class RXtraits = regex_traits <Elem> > class regex_iterator;

typedef regex_iterator <const char*>
     cregex_iterator;
typedef regex_iterator <const wchar_t*>
     wcregex_iterator;
typedef regex_iterator <string::const_iterator>
     sregex_iterator;
typedef regex_iterator <wstring::const_iterator>
     wsregex_iterator;

} }

This class template hides the details that we looked at in the first section. A search program similar to the last example but using regex_iterator looks like this.

Example 19.9. Searching (regexiter/rgxiterator.cpp)

#include <regex>
#include <iostream>
#include <string>
#include <iterator>
#include <algorithm>
using std::tr1::regex; using std::tr1::cregex_iterator;
using std::tr1::cmatch;
using std::cout; using std::string;
using std::ostream_iterator; using std::copy;

namespace std {      // add inserter to namespace std
template <class Elem, class  Alloc>
basic_ostream <Elem, Alloc>& operator <<(
  basic_ostream <Elem, Alloc>& out, const cmatch& val)
  {  // insert cmatch object into stream
  static string empty("[empty]");
  return out << (val.length() ? val.str() : empty);
  }
}

int main()
  { // demonstrate use of cregex_iterator
  const char *expr = "a*|c";
  const char *tgt = "bcd";
  regex rgx(expr);
  const char *end = tgt + strlen(tgt);
  cregex_iterator first(tgt, end, rgx), last;
  ostream_iterator <cmatch> out(cout, "\n");
  copy(first, last, out);
  return 0;
  }

The program creates a regular expression object, rgx, that holds the regular expression to search for. Then the program creates a regex_iterator object,[2] first, passing two iterators that delineate the target text and passing the regular expression object. The program also creates an end-of-sequence iterator, last. These two iterators describe a sequence of match_results objects, with successive elements in the sequence holding the results of successive repetitive searches. The program then creates an ostream_iterator<cmatch> object, which inserts cmatch objects into its target stream, using the operator<< that the program defined earlier, and passes all three iterators to the standard copy algorithm, which copies the contents of the range defined by [first, last) into the target, out. The tricky code that we had to write in the loop in the previous example is all handled in the regex_iterator's operator++, which is called inside copy.

[2] The type cregex_iterator is a regex_iterator that looks at sequences delineated by char*s.

template <class BidIt,
    class Elem =
      typename iterator_traits<BidIt>::value_type,
    class RXtraits = regex_traits<Elem>>
  class regex_iterator {
public :
    // NESTED TYPES
  typedef basic_regex<Elem, RXtraits> regex_type;
  typedef match_results<BidIt> value_type;
  typedef std::forward_iterator_tag iterator_category;
  typedef std::ptrdiff_t difference_type;
  typedef const match_results<BidIt> * pointer;
  typedef const match_results<BidIt>& reference;

    // CONSTRUCTING AND ASSIGNING
  regex_iterator();
  regex_iterator(BidIt, BidIt, const regex_type & re,
    regex_constants::match_flag_type =
      regex_constants::match_default);
  regex_iterator(const regex_iterator&);
  regex_iterator & operator = (const regex_iterator&);

    // DEREFERENCING
  const match_results <BidIt>& operator*();
  const match_results <BidIt> * operator->();

    // MODIFYING
  regex_iterator& operator++();
  regex_iterator operator++(int);

    // COMPARING
  bool operator==(const regex_iterator&) const;
  bool operator! = (const regex_iterator&) const;

private:
    // exposition only:
  BidIt first, last;
  const regex_type *pre;
  match_flag_type flags;
  match_results <BidIt> match;
  };

The class template describes an object that can serve as a forward iterator for an unmodifiable sequence of character sequences that match a regular expression.

The template argument BidIt must be a bidirectional iterator. It names the type of the iterator that will designate the target character sequence when an iterator object is created. The template arguments Elem and RXtraits name the character type and the traits type, respectively, for the regular expression type, basic_regex<Elem, Rxtraits>, that will be passed to a regex_iterator object's constructor. By default, these arguments are derived from the first type argument, BidIt.

You create a regex_iterator object by passing two iterators that delineate a character range to be searched and a basic_regex object that holds the regular expression to search for. The resulting object points at the first matching subsequence in the target sequence. Each application of operator++ advances the iterator to point at the next matching subsequence, until there are no more matching subsequences. At that point, the iterator compares equal to the end-of-sequence iterator, which is created with the default constructor.

The template defines several nested types (Section 19.2.1) and provides three constructors and an assignment operator (Section 19.2.2). An object can be dereferenced with operator* and operator-> (Section 19.2.3), and can be incremented, to point at the next element in the output sequence, with operator++ (Section 19.2.4). Two regex_iterator objects of the same type can be compared for equality (Section 19.2.5). Four predefined types for the most commonly used character types are described in Section 19.2.6.

The definition of this template includes several members marked as exposition only:. These members are used in the descriptions of some of this template's member functions that follow. Keep in mind that these members aren't required by TR1. The rule is that the member functions have to act as if they were implemented according to the descriptions.

19.2.1. Nested Types

typedef basic_regex <Elem, RXtraits> regex_type;

The type is a synonym for basic_regex<Elem, RXtraits>.

The typedef names the type of the regular expression object that will be used in searches. In most cases the regular expression object traffics in the same element type as the target text, so Elem is simply the value type of the bidirectional iterator type BidIt. For example, if the target text to be searched is going to be designated by a const char*, the regular expression object will ordinarily have type basic_regex<char, regex_traits<char>>. This typedef is especially handy if you prefer qualified id's over using declarations.

Example 19.10. Nested Type Name (regexiter/typename.cpp)

# include <regex>
#include <iostream>
#include <fstream>
#include <iterator>
#include <algorithm>
#include <string>

typedef std::string::const_iterator seq_t;
typedef std::tr1::regex_iterator <seq_t> rgxiter;
typedef rgxiter::regex_type rgx_t;
typedef std::tr1::match_results <seq_t> match_t;

namespace std { // add inserter to namespace std
template <class Elem, class Alloc>
std::basic_ostream <Elem,  Alloc>& operator <<(
  std::basic_ostream <Elem, Alloc>&  out,
  const match_t & val)
  { // insert cmatch object into stream
  static std::string  empty ("[ empty ]");
  return out << (val.length () ? val.str () : empty);
  }
}

int main()
  { // split out words from text file
  rgx_t rgx ("[[: alnum :]_#]+ ");
  ifstream input (" typename .cpp ");
  std::string  str;
  while (std::getline (input, str))
    { // split out words from a line of text
    rgxiter first (str.begin (), str .end (), rgx), last;
    std::ostream_iterator <rgxiter::value_type>
      tgt (std::cout, "\n"));
    std::copy (first, last, tgt);
    }
  return 0;
  }

typedef match_results <BidIt>  value_type;
typedef std::forward_iterator_tag  iterator_category;
typedef std::ptrdiff_t  difference_type;
typedef const match_results <BidIt>* pointer;
typedef const match_results <BidIt>& reference;

These are the usual typedefs for an iterator type.

19.2.2. Constructing and Assigning

regex_iterator <BidIt, Elem, RXtraits>::regex_iterator ();

The constructor constructs an end-of-sequence iterator.

regex_iterator <BidIt, Elem,   RXtraits>::regex_iterator (
  BidIt first1, BidIt last1,
  const regex_type & re,
  regex_constants::match_flag_type flgs =
    regex_constants::match_default);

The constructor constructs an object with initial values first and last equal to first1 and last1, respectively; pre equal to &re;[3] and flags equal to flgs. The constructor then calls regex_search(first, last, match, *pre, flags); if that call returns false, it marks the object as an end-of-sequence iterator.

[3] Note that the iterator holds the address of the regular expression object, not a copy. Once the regular expression object is destroyed, the iterator can no longer be used.

In other words, the constructor stores the various search parameters, then searches for the first occurrence of text matching re in the range of characters pointed at by [first1, last1). If the search succeeds, the result is stored in the member data object match. If the search fails, there are no matches, and the object is marked as an end-of-sequence iterator, that is, an object that compares equal to a default-constructed object.

Example 19.11. End-of-Sequence (regexiter/endofsequence.cpp)

#include <regex>
#include <string>
#include <iostream>
using std::string ; using std::cout;
typedef string::const_iterator seq_t;
typedef std::tr1::regex_iterator <seq_t> rgxiter;
typedef rgxiter::regex_type rgx_t;

int main()
  { // constructing regex iterator objects
  rgx_t rgx ("not found ");
  string target (" this is text ");
  rgxiter first (target.begin (), target.end (), rgx);
  rgxiter last;
  if (first ==  last)
    cout << " regular expression not found \n";
    return 0;
  }

regex_iterator <BidIt, Elem, RXtraits>::regex_iterator (
  const regex_iterator & right);
regex_iterator &
  regex_iterator <BidIt, Elem, RXtraits>::operator= (
  const regex_iterator & right);

The copy constructor and the assignment operator copy their argument into *this. After the operation, *this == right.

19.2.3. Dereferencing

const match_results <BidIt>&
  regex_iterator <BidIt,  Elem, RXtraits>::operator* () const;
const match_results <BidIt>*
  regex_iterator <BidIt,  Elem, RXtraits>::operator-> () const;

The behavior of a program that calls either of these member operators on an end-of-sequence iterator is undefined. Otherwise, the first member operator returns a reference to the contained object match, and the second member operator returns a pointer to the contained object match.

The contained object match holds the results of the most recent successful search, so you can use these operators to look at those results, just as if you had written a call to regex_search yourself and passed a match_results object.

Example 19.12. Examining Search Results (regexiter/result.cpp)

#include <regex>
#include <iostream>
#include <iomanip>
#include <string>
using std::string; using std::cout; using std::setw;

typedef string:: const_iterator  seq_t;
typedef std::tr1::regex_iterator <seq_t> rgxiter;
typedef rgxiter:: regex_type  rgx_t;
typedef rgxiter:: value_type  match_t;

static void show (const match_t & match)
  { // show contents of match_t object
  for (int idx = 0; idx <match.size (); ++ idx)
    { // show match[idx]
    cout << idx << ": ";
    if (match [ idx ]. matched)
      cout << setw (match.position(idx)) << ""
        << match.str(idx) << '\n';
    else
      cout << "[not matched]";
    }
  }

int main()
  { // demonstrate regex  iterator dereferencing
  string id =
    " ([[: alpha :]]+)([[: space :]]+)([[: digit :]]{2,5}) ";
  rgx_t model_descr (id);
  string item ("Emperor 400");
  rgxiter iter (item.begin (), item.end (), model_descr);
  show (*iter);                                       // operator*
  cout << iter->str () < < '\n';  // operator->
  return 0;
  }

19.2.4. Modifying

regex_iterator
  regex_iterator <BidIt, Elem, RXtraits>::operator++ (int)
    { regex_iterator tmp (* this); ++* this ; return tmp ;  }
regex_iterator &
  regex_iterator <BidIt, Elem, RXtraits>::operator++ ();

The first member function makes a copy of *this, increments *this, and returns the copy.

The second member function begins by constructing a local variable referred to here as start, initialized with the value match[0].second.

If match.length() == 0 and start == end, it marks the object as an end-of-sequence iterator and returns *this.

Otherwise, if match.length() == 0, the operator creates a temporary object, temp_flags, of type match_flag_type, holding the value flags | match_not_null | match_continuous. It then calls regex_search(start, last, match, *pre, temp_flags). If the call returns true, the operator returns *this. Otherwise, it increments start and moves to the following step.

The operator next sets flags to flags | match_prev_avail and calls regex_search(start, last, match, *pre, flags). If the call returns false, the operator marks the object as an end-of-sequence iterator. The call returns *this.

Whenever a call to regex_search returns TRue, the operator adjusts the contents of match so that match.prefix().first is equal to the previous value of match[0].second; for each value of idx for which match[idx]. matched is true, match[idx].position() returns the value of distance(begin, match[idx].first).

You probably recognized most of this text as a description of the repetitive search algorithm we developed in Section 19.1. But, the last paragraph adds a twist: Regardless of how it got there, the prefix after a successful search is the text from the end of the previous successful match up to the current match, and all the match positions are offsets from the start of the original text sequence.

Look at how the output showing the various matches is formatted in this example, which is similar to the previous one.

Example 19.13. Incrementing (regexiter/increment.cpp)

#include <regex>
#include <iostream>
#include <iomanip>
#include <string>
using std::string; using std::cout; using std::setw;

typedef string:: const_iterator seq_t;
typedef std::tr1::regex_iterator <seq_t> rgxiter;
typedef rgxiter:: regex_type rgx_t;
typedef rgxiter:: value_type match_t;

static void show(const match_t & match)
  { // show contents of  match_t object
  for (int idx = 0; idx <match.size(); ++idx)
    { // show match[idx]
    cout << idx << ": ";
    if (match[idx]. matched)
      cout << setw (match.position (idx)) << ""
        << match.str (idx) << '\n';
    else
      cout << "[not matched]";
    }
  }

int main()
  { // demonstrate regex_iterator dereferencing
  string id =
    " ([[:alpha:]]+)([[:space:]]+)([[:digit:]]{2,5}) ";
  rgx_t   model_descr (id);
  string item ("Emperor 280, Emperor 400, Whisper 60 ");
  rgxiter first (item.begin(), item.end(), model_descr);
  rgxiter last;
  cout << "  " << item <<'\n';
  while (first !=last)
    show (* first ++);
  return 0;
  }

19.2.5. Comparing

bool regex_iterator<BidIt, Elem, RXtraits>::operator==(
  const regex_iterator& right) const;
bool regex_iterator<BidIt, Elem, RXtraits>::operator!=(
  const regex_iterator& right) const
  { return !(*this == right); }

The first member operator returns true only if *this and right are both end-of-sequence iterators or if first == right.first, last == right. last, pre == right.pre, flags == right.flags, and match == right .match. The second member operator returns !(*this == right).

This rather lengthy description says what you'd expect: If you create two regex_iterator objects with the same arguments or by copying one onto the other, they compare equal. If you increment two equal iterators the same number of times, they still compare equal. As long as the searcheseither at construction or as part of an incrementsucceed, the object does not compare equal to an end-of-sequence iterator. When a search fails, as we saw earlier, the iterator object is marked as an end-of-sequence iterator; at that point, it compares equal to any other end-of-sequence iterator.

Example 19.14. Comparing (regexiter/compare.cpp)

# include <regex>
#include <iostream>
#include <string>
using std::tr1::regex; using std::tr1::regex_iterator;
using std::string; using std::cout;

typedef regex_iterator<string::const_iterator> iter_t;

static void show_equal(const char *title,
  const iter_t& iter0, const iter_t& iter1)
  { // show equality of iterator objects
  cout << title << "\n"
    << (iter0 == iter1? "equal" : "not equal") << '\n';
  }

int main()
  {   // demonstrate regex iterator comparison operators
  regex rgx0("abc"), rgx1("abc");
  string tgt0("abc"), tgt1("abc");
  iter_t iter0(tgt0.begin(), tgt0.end(), rgx0);
  iter_t iter1(tgt0.begin(), tgt0.end(), rgx1);
  show_equal(
    "same range, different regular expression objects",
    iter0, iter1);
  iter_t iter2(tgt0.begin() + 1, tgt0.end(), rgx0);
  show_equal(
    "different range, same regular expression objects",
    iter0, iter2);
  iter_t iter3, iter4;
  show_equal("default constructed",
    iter3, iter4);
  show_equal(
    "non-default constructed and default constructed",
    iter0, iter4);
  ++iter0;  // move past final match
  show_equal(
    "incremented to end and default constructed",
    iter0, iter4);
  return 0;
  }

19.2.6. Predefined regex_iterator Types

typedef regex_iterator<const char*>
  cregex_iterator;
typedef regex_iterator<const wchar_t*>
  wcregex_iterator;
typedef regex_iterator<string::const_iterator>
  sregex_iterator;
typedef regex_iterator<wstring::const_iterator>
  wsregex_iterator;

As always, there are four predefined regex_iterator types for text sequences held in arrays of char and wchar_t and in basic_string objects holding elements of type char and wchar_t.


Section 19.3. The regex_token_iterator Class Template

19.3. The regex_token_iterator Class Template

The class template regex_token_iterator is defined in the header <regex>.

namespace std {    // C++ standard library
 namespace tr1 {    // TR1 additions

      // CLASS TEMPLATE regex_token_iterator
template<class BidIt,
  class Elem = typename iterator_traits<BidIt>::value_type,
  class RXtraits = regex_traits<Elem> >
    class regex_token_iterator;

typedef regex_token_iterator<const char*>
  cregex_token_iterator;
typedef regex_token_iterator<const wchar_t*>
  wcregex_token_iterator;
typedef regex_token_iterator<string::const_iterator>
  sregex_token_iterator;
typedef regex_token_iterator<wstring::const_iterator>
  wsregex_token_iterator;

} }

Dereferencing a regex_iterator object produces a match_results object that represents the current match. As we saw in several earlier examples, the returned object can, in turn, be used to get at various submatches of a successful match. A regex_token_iterator object provides direct access to submatches. When you construct a regex_token_iterator object, you pass an additional set of numeric arguments that designate the desired submatches. Each time you increment the iterator, it advances to the next submatch. When it runs out of submatches, the iterator moves to the next match and starts the list of submatches over again. So the explicit loop over submatches that we used earlier can be eliminated.

Example 19.15. Searching(regexiter/tokiterator.cpp)

#include <regex>
#include <iostream>
#include <string>
using std::string; using std::cout;

typedef string::const_iterator seq_t;
typedef std::tr1::regex_token_iterator<seq_t> rgxiter;
typedef rgxiter::regex_type rgx_t;
typedef rgxiter::value_type match;

int main()
  { // demonstrate regex_token_iterator
  string id =
    "([[:alpha:]]+)([[:space:]]+)([[:digit:]]{2,5})";
  rgx_t model_descr(id);
  string item("Emperor 280, Emperor 400, Whisper 60");
  int fields[] = {0,1,3};
  rgxiter first(item.begin(), item.end(),
    model_descr, fields);
  rgxiter last;
  cout << item << '\n';
  while(first != last)
    cout <<*first++ << '\n';
  return 0;
  }

This program is much simpler than the similar one in Section 19.2.4 but doesn't provide as much information. That's because operator* on a regex_-token_iterator object returns a sub_match object, which points at a portion of the target text and, unlike match_results, does not know how far into the target text this match occurred.

template<class BidIt,
    class Elem =
      typename iterator_traits<BidIt>::value_type,
    class RXtraits = regex_traits<Elem> >
  class regex_token_iterator {
public:
      // NESTED TYPES
  typedef basic_regex<Elem, RXtraits> regex_type;
  typedef sub_match<BidIt> value_type;
  typedef std::forward_iterator_tag iterator_category;
  typedef std::ptrdiff_t difference_type;
  typedef const sub_match<BidIt>* pointer;
  typedef const sub_match<BidIt>& reference;

      // CONSTRUCTING AND ASSIGNING
  regex_token_iterator();
  regex_token_iterator(BidIt first, BidIt last,
    const regex_type& re, int submatch = 0,
    regex_constants::match_flag_type flags =
      regex_constants::match_default);
  regex_token_iterator(BidIt first, BidIt last,
    const regex_type& re,
    const std::vector<int> submatches,
    regex_constants::match_flag_type flags =
      regex_constants::match_default);
  template<std::size_t N>
  regex_token_iterator(BidIt first, BidIt last,
    const regex_type& re, const int(&submatches)[N],
    regex_constants::match_flag_type flags =
      regex_constants::match_default);
  regex_token_iterator(const regex_token_iterator&);
  regex_token_iterator& operator=(
    const regex_token_iterator&);

    // DEREFERENCING
  const sub_match<BidIt>& operator*() const;
  const sub_match<BidIt> *operator->() const;

    // MODIFYING
  regex_token_iterator& operator++();
  regex_token_iterator operator++(int);

    // COMPARING
  bool operator==(const regex_token_iterator& right) const;
  bool operator!=(const regex_token_iterator& right) const;

private:
  // exposition only:
  typedef regex_iterator<BidIt, Elem, RXtraits> iter;
  iter pos;
  std::vector <int> subs;
  std::size_t N;
  };

The class template describes an object that can serve as a forward iterator for an unmodifiable sequence of character sequences that match various parts of a regular expression.

The template argument BidIt must be a bidirectional iterator. It names the type of the iterator that will designate the target character sequence when an iterator object is created. The template arguments Elem and RXtraits name the character type and the traits type, respectively, for the regular expression type, basic_regex<Elem, Rxtraits>, that will be passed to a regex_token_iterator object's constructor. By default, these arguments are derived from the first type argument, BidIt.

You create a regex_token_iterator object by passing two iterators that delineate a character range to be searched and a basic_regex object that holds the regular expression to search for, just as you do for a regex_iterator object. In addition, though, you pass one or more integer values that identify the various submatches that you want to iterate through. The constructors search for the first text subsequence that matches the regular expression. The resulting object points at the first of the designated submatches in the matching subsequence. Each application of operator++ moves to the next submatch. If the list of submatches has been exhausted, the operator searches for the next text subsequence that matches the regular expression and points at the first of the designated submatches in the matching subsequence. If there are no more matching subsequences, the iterator compares equal to the end-of-sequence iterator, which is created with the default constructor.

The template defines several nested types(Section 19.3.1) and provides five constructors and an assignment operator(Section 19.3.2). An object can be dereferenced with operator* and operator->(Section 19.3.3) and can be incremented to point at the next element in the output sequence with operator++(Section 19.3.4). Two regex_token_iterator objects of the same type can be compared for equality(Section 19.3.5). Four predefined types for the most commonly used character types are described in Section 19.3.6.

The definition of this template includes several members marked as exposition only:. These members are used in the descriptions that follow of some of the member functions of this template. Keep in mind that these members aren't required by TR1. The rule is that the member functions have to act as if they were implemented according to the descriptions.

The descriptions also use a couple of technical terms that are defined in TR1. A suffix iterator is an iterator object of type regex_token_iterator that points at the final sequence of characters in the target text. The current match is (*pos).prefix() if subs[N] is -1; otherwise, (*pos)[subs[N]].

That last term is the key to understanding how a regex_token_iterator determines the sequence of submatches to return. When you construct a regex_token_iterator object, you pass one or more integer values, as described in Section 19.3.2. Those values, in turn, determine which submatches will be returned and in what order. A value of -1 refers to the text beginning at the end of the previous matchor at the beginning of the text sequence when the iterator object is first constructedand ending at the beginning of the current match. After the final, failed, search, a value of -1 refers to the text from the end of the last successful searchor the beginning of the text sequence if no search succeededto the end of the text sequence. Any other value refers to the corresponding capture group. Thus, a value of 0 means the entire matched text, a value of 1 means the first capture group, and so on. Each time you increment an iterator object, it advances to the next subgroup, as determined by those integer values. When it's gone through all those values, it moves to the next match and repeats the sequence of values.

19.3.1. Nested Types

typedef basic_regex<Elem, RXtraits> regex_type;

The type is a synonym for basic_regex<Elem, RXtraits>.

The typedef names the type of the regular expression object that will be used in searches. For details, see the discussion in Section 19.2.1.

typedef basic_string<Elem> value_type;
typedef std::forward_iterator_tag iterator_category;
typedef std::ptrdiff_t difference_type;
typedef const basic_string<Elem>* pointer;
typedef const basic_string<Elem>& reference;

These are the usual typedefs for an iterator type.

19.3.2. Constructing and Assigning

regex_token_iterator<BidIt, Elem, RXtraits>::
   regex_token_iterator();

The constructor constructs an end-of-sequence iterator.

regex_token_iterator<BidIt, Elem, RXtraits>::
  regex_token_iterator(
  BidIt first, BidIt last,
  const regex_type& re, int submatch = 0,
  regex_constants::match_flag_type flags =
    regex_constants::match_default);
regex_token_iterator<BidIt, Elem, RXtraits>::
  regex_token_iterator(
  BidIt first, BidIt last,
  const regex_type& re,
  const std::vector<int> submatches,
  regex_constants::match_flag_type flags =
    regex_constants::match_default);
template<std::size_t N>
regex_token_iterator<BidIt, Elem, RXtraits>::
  regex_token_iterator(
  BidIt first, BidIt last,
  const regex_type& re, const int (&submatches)[N],
  regex_constants::match_flag_type flags =
    regex_constants::match_default);

The first constructor stores the value of submatch in subs. The second and third constructors each copy their argument submatch into subs.

The constructors then set the value of N to 0 and the value of pos to iter(first, last, re, flags). If pos is not an end-of-sequence iterator, the constructors set res to the address of the current match. Otherwise, if any of the values stored in subs is -1, the constructors set *this to be a suffix iterator that points at the entire text sequence [first, last). Otherwise, the constructors set *this to an end-of-sequence iterator.

The first constructor takes exactly one integer argument, which designates the sub-group to be returned by the iterator. To see the entire matching text, pass the value 0. To see the nth capture group, pass n. To see the text that precedes the match, pass -1.

Example 19.16. Viewing a Single Submatch(regexiter/single.cpp)

#include <regex>
#include <iostream>
#include <string>
using std::string; using std::cout;

typedef string::const_iterator seq_t;
typedef std::tr1::regex_token_iterator<seq_t> rgxiter;
typedef rgxiter::regex_type rgx_t;
typedef rgxiter::value_type match;

static void show(int field)
  {   // demonstrate single-field constructor
  string id =
    "([[:alpha:]]+)([[:space:]]+)([[:digit:]]{2,5})";
  rgx_t model_descr(id);
  string item("Emperor 280, Emperor 400, Whisper 60");
  rgxiter first(item.begin(), item.end(),
    model_descr, field);
  rgxiter last;
  while (first != last)
    cout << *first++ << '\n';
  }
int main()
  {  // demonstrate regex_token_iterator single-field constructor
  cout << "Full match:\n";
  show(0);
  cout << "\nModel name:\n";
  show(1);
  cout << "\nModel number:\n";
  show(3);
  cout << "\nSeparators :\n";
  show(-1);
  return 0;
  }

The second and third constructors take one or more integer arguments, either as a C++ vector<int> or as a C-style array of int.

Example 19.17. Viewing Multiple Submatches(regexiter/multiple.cpp)

#include <regex>
#include <iostream>
#include <string>
#include <vector>
using std::string; using std::cout; using std::vector;

typedef string::const_iterator seq_t;
typedef std::tr1::regex_token_iterator<seq_t> rgxiter;
typedef rgxiter::regex_type rgx_t;
typedef rgxiter::value_type match;

static void show(const vector <int>&, fields)
  {   // demonstrate multiple-field constructor
  string id =
    "([[:alpha:]]+)([[:space:]]+)([[:digit:]]{2,5})";
  rgx_t model_descr(id);
  string item("Emperor 280, Emperor 400, Whisper 60");
  rgxiter first(item.begin(), item.end(),
    model_descr, fields);
  rgxiter last;
  while(first != last)
    cout << *first++ << '\n';
  }
int main()
  {   // demonstrate regex_token_iterator multiple-field constructor
  vector<int> fields;
  fields.push_back(0);
  cout <<"Full match:\n";
  show(fields);
  fields.push_back(3);
  cout <<"Full match, model number:\n";
  show(fields);
  fields.push_back(1);
  cout <<" Full match, model number,  model name :\n";
  show(fields);
  return 0;
  }

regex_token_iterator<BidIt,  Elem, RXtraits>::
  regex_token_iterator(
  const regex_token_iterator& right);
regex_token_iterator&
regex_token_iterator<BidIt,  Elem, RXtraits>::
  operator=(
  const regex_token_iterator& right);

The copy constructor and assignment operator each copy their argument into *this. After the operation, *this == right.

19.3.3. Dereferencing

const basic_string <Elem>&
  regex_token_iterator<BidIt, Elem, RXtraits>::
  operator*() const;
const basic_string <Elem>*
  regex_token_iterator<BidIt, Elem, RXtraits>::
  operator->() const;

The behavior of a program that calls either of these member operators on an end-of-sequence iterator is undefined. Otherwise, the first member operator returns a reference to the current match, and the second member operator returns a pointer to the current match.

19.3.4. Modifying

regex_token_iterator
regex_token_iterator<BidIt,  Elem, RXtraits>::
  operator++(int)
    { regex_token_iterator tmp(*this); ++*this; return tmp;}
regex_token_iterator&
  regex_token_iterator<BidIt,  Elem, RXtraits>::operator++();

The first member function makes a copy of *this, increments *this, and returns the copy.

If the stored iterator pos is an end-of-sequence iterator, the second operator marks *this as an end-of-sequence iterator. Otherwise, the operator increments the stored value N; if the result is equal to subs.size(), it sets the stored value N to 0 and increments the stored iterator pos. If incrementing the stored iterator leaves it unequal to an end-of-sequence iterator, the operator does nothing further. Otherwise, if the end of the preceding match was at the end of the character sequence, the operator marks *this as an end-of-sequence iterator. Otherwise, the operator repeatedly increments the stored value N until N == subs.size(), in which case it marks *this as an end-of-sequence iterator or until subs[N] == -1, thus ensuring that the next dereference will return the suffix of the last successful match. In all cases, the operator returns *this.

To better understand how a submatch selector of -1 works, think of the target text as a sequence of subsequences U1M1U2M2 ... UmMmUm+1, where the various subsequences Mi match the regular expression, and the various subsequences Ui do not match the regular expression. A selector of -1 selects the Ui subsequences, including the final nonmatching subsequence Um+1 if it is not empty.

Example 19.18. Selecting Separators(regexiter/select.cpp)

#include <regex>
#include <iostream>
#include <string>
using std::string; using std::cout;

typedef string::const_iterator seq_t;
typedef std::tr1::regex_token_iterator<seq_t> rgxiter;
typedef rgxiter::regex_type rgx_t;
typedef rgxiter::value_type match;

int main()
  { // demonstrate use of selector value -1
  string csv(" [[: space :]]*,[[: space :]]*");
  rgx_t rgx(csv);
  string data(" Ron   Mars,   2114 East St .,   Biloxi, MI");
  rgxiter first(data.begin(), data .end(), rgx,   -1);
  rgxiter last;
  while(first !=  last)
    cout <<*first++ << '\n';
  return 0;
  }

19.3.5. Comparing

bool regex_token_iterator<BidIt, Elem, RXtraits>::
  operator==(
  const regex_token_iterator& right) const;
bool regex_token_iterator<BidIt, Elem,  RXtraits>::
  operator!=(
  const regex_token_iterator& right) const
  { return !(*this == right); }

The first member function returns true if *this and right are both end-of-sequence iterators or if both are suffix iterators that point at the same text sequence. Otherwise, if either of them is an end-of-sequence iterator or a suffix iterator, the member function returns false. Otherwise, the member function returns pos == right.pos&& subs == right.subs&& N == right.N.

The second member function returns !(*this == right).

Two regex_token_iterator objects compare equal if they were constructed from the same regular expression argument and equal other arguments, and they have been incremented the same number of times. When you make a copy of a regex_token_iterator object, the first requirement is obviously satisfied, so a copy of a regex_token_iterator object is equal to the object it was copied from if both have been incremented the same number of times since the copy was made.

Example 19.19. Comparing(regexiter/comparetok.cpp)

#include <regex>
#include <iostream>
#include <string>
using std::tr1::regex;
using std::tr1::regex_token_iterator;
using std::string; using std::cout;

typedef string::const_iterator siter;
typedef regex_token_iterator<siter> iter_t;

static void   show_equal(const char *title,
  const iter_t& iter0, const iter_t& iter1)
  { // show equality of iterator objects
  cout <<title <<"\n"
    <<(iter0 == iter1 ? " equal " : " not equal ") << '\n';
  }

int main()
  { // demonstrate regex_token_iterator comparison operators
  string csv(" [[: space :]]*,[[: space :]]*");
  regex rgx(csv);
  string data(" Ron Mars,  2114 East St ., Biloxi, MI");
  int selector0 [] = { 0, 1 };
  int selector1 [] = { 0, 1 };
  int selector2 [] = { 1, 0 };
  iter_t iter0(data.begin(), data.end(), rgx, selector0);
  iter_t iter1(data.begin(), data.end(), rgx, selector0);
  show_equal("equal arguments", iter0, iter1);
  iter_t iter2(data.begin(), data.end(), rgx, selector1);
  show_equal("equal selectors", iter0, iter2);
  iter_t iter3(data.begin(), data.end(), rgx, selector2);
  show_equal("unequal selectors", iter0, iter3);

  iter_t iter4(++ iter0);
  show_equal("copy", iter0, iter4);
  ++ iter0;
  show_equal("unequal increments", iter0, iter4);
  ++ iter4;
  show_equal("equal increments", iter0, iter4);
  return 0;
  }

19.3.6. Predefined regex_token_iterator Types

typedef regex_token_iterator<const char *>
  cregex_token_iterator;
typedef   regex_token_iterator<const wchar_t *>
  wcregex_token_iterator;
typedef   regex_token_iterator<string::const_iterator>
  sregex_token_iterator;
typedef   regex_token_iterator<wstring::const_iterator>
  wsregex_token_iterator;

As always, there are four predefined regex_token_iterator types for text sequences held in arrays of char and wchar_t and in basic_string objects holding elements of type char and wchar_t.


Exercises

Exercise 1

For each of the following errors, write a simple test case containing the error, and try to compile it. In the error messages, look for the key words that relate to the error in the code.

  1. Attempting to construct a regex_iterator object by passing a pair of iterators whose character type is different from the regex_iterator type's character type

  2. Attempting to construct a regex_iterator object by passing a regular expression object whose element type or traits type is different from the regex_iterator type's element type or traits type

  3. Attempting to construct a regex_token_iterator object by passing a pair of iterators whose character type is different from the regex_-token_iterator type's character type

  4. Attempting to construct a regex_token_iterator object by passing a regular expression object whose element type or traits type is different from the regex_token_iterator type's element type or traits type

  5. Attempting to construct a regex_token_iterator object by passing a field specifier as a pointer to int instead of an array of int

  6. Attempting to decrement a regex_iterator object

  7. Attempting to decrement a regex_token_iterator object

Exercise 2

In the first part of this chapter, I mentioned that it's a little hard to reuse the brute-force loop. In this exercise, we look at a couple of possible approaches to reuse and at doing the same thing with regular expression iterators.

  1. Write a program that has a copy of the code of the search function in Example 19.8. Change the search function so that for a successful match, it shows the contents of the first capture group instead of the entire match. Now use the function to copy to cout all text that occurs between the tags "<CODE>" and "</CODE>"[4] in an HTML file of your choosing.[5]

    [4] That is, search for text matching the regular expression "<CODE>(.*?)</CODE>"; for each successful match, write out the contents of capture group 1.

    [5] Hint: Read the entire text file into a string object by creating an if stream object to read the file and a basic_ostringstream object to build the string, and inserting the buffer returned by the ifstream's member function rdbuf() into the basic_ostringstream object.

  2. Now write another program that has a copy of the code of the search function in Example 19.8. Change the search function into a template function with a template type parameter named Fn and an additional function call argument, Fn func. Also replace the code that shows the match by inserting it into cout with a call to func(match). Now use the function for the same search as in the preceding part of this exercise.[6]

    [6] You'll have to write a callable type whose function call operator takes a match_results object and copies the first capture group to cout.

  3. Write a program that uses a regex_iterator object to do the same search.

  4. Write a program that uses a regex_token_iterator object to do the same search.

  5. Now change all four programs to copy to cout all text that occurs between the tags "<CODE>" and "</CODE>" or between the tags "<PRE>" and "</PRE>".[7]

    [7] That is, search for text matching the regular expression "<(CODE|PRE)>(.*?)</\1>"; for each successful match, write out the contents of capture group 2.

Exercise 3

Use a pair of regex_iterator objects to search for valid host-names[8] in an HTML file, and use the utility function you wrote for Exercise 2 in Chapter 18 to show the contents of each successful match.

[8] See Exercise 2 in Chapter 17 for a suitable regular expression.

Exercise 4

Write a program that uses a pair of regex_token_iterator objects to extract data fields from a comma-separated file. Don't forget to allow for spaces and tabs before and after each comma.[9]

[9] Hint: Write a regular expression that describes the separator, and use an iterator that shows the text that doesn't match the separator.

Exercise 5

Write a program that puts the integer values 1 and 4 into a vector<int> and passes that vector as the field specifier in the constructor of a regex_token_iterator object. Use that object to search for your favorite regular expression. Now put the same values into an array of int, pass that array to the constructor, and repeat the search. What happens if the field index is higher than the index of the last capture group in the regular expression? What happens if you repeat a field index in the initializer?

Exercise 6

HTML cross-references have the form <A HREF="reference"> text</A>" and <A NAME="reference">text</A>". The first is a link, and the second is the target of a link. In both cases, the reference is in quotes. Write a program that uses a pair of regex_token_iterator objects to search for cross-references in an HTML file and shows, for each cross-reference, either "HREF=" or "NAME=", as appropriate, followed by text of the reference.


Chapter 20. Formatting and Text Replacement

Give this much to the Luftwaffe. When it knocked down our buildings, it didn't replace them with anything more offensive than rubble. We did that.

Speech in London, December 1987
CHARLES PHILIP ARTHUR GEORGE,
PRINCE OF WALES

Suppose that you've been assigned to write a program that will send personalized e-mail to a list of pet owners whose names and e-mail addresses are stored in a file of comma-separated fields, one line per person. The fields in each line are, in order, the person's e-mail address, first name, last name, pet's name, and the kind of animal it is.[1] Since you read Chapter 19, you know how to write a regular expression to extract fields from a comma-separated list. Now you need to extract that information and insert it into the right places in the e-mail message. A brute-force approach might look like this.[2]

[1] Of course, real pet owners often have more than one pet. But let's not make things too complicated.

[2] In this example, I've put the address file in a text string rather than write a separate file. In the real world, of course, instead of using an istringstream to read the address information, you'd use an ifstream.

Example 20.1. Inserting Fields (regexform/inserting.cpp)

#include <regex>
#include <iostream>
#include <string>
#include <sstream>
using std::tr1::regex; using std::tr1::smatch;
using std::cout; using std::string;
using std::istringstream;

static const string addrlist =
"joebob@notarealaddress.org, Joe, Bob, Bubba, iguana \n"
"missy@notarealaddress.org, Missy, Treadwell,"
  "Reginald Addington Farnsworth II,"
  "prize - winning Toy Poodle \n"
"killer@notarealaddress.org, Spike, Redwood ,"
  "Fangs, snake \n"
"kitten@notarealaddress.org, Sally, Smith ,"
  "Mr.Bubbles, goldfish \n";

static void write_letter (const smatch& match)
  {
  cout << "To :" << match.str (1) << ' \n ';
  cout << "Dear" << match.str (2) << ",\n";
  cout << "I ' m sure your" << match.str (5)
    << "," << match.str (4) << ",\n";
  cout << "as well as all the other pets in the"
    << match.str (3) << "family,\n";
  cout << "will enjoy our latest offering,"
    << "Universal - Ultra - Mega Vitamins,\n";
  cout << "Now available for all kinds of animals,"
    << "including" << match.str (5) << "s.\n";
  cout << "Don't delay, get some today !\n";
  }

int main ()
  {
  regex rgx (
    "(.*)[[: space :]]*,[[: space :]]*"
    "(.*)[[: space :]]*,[[: space :]]*"
    "(.*)[[: space :]]*,[[: space :]]*"
    "(.*)[[: space :]]*,[[: space :]]*"
    "(.*)");
  smatch match;
    istringstream addresses (addrlist);
    string address;
    while (getline (addresses, address)
      &&  regex_match (address, match, rgx))
         write_letter (match);
    return 0;
    }

The function write_letter is rather poorly designed. First, it ought to format its text into a string or a stream so that the rest of the program can more easily manipulate it. Second, and more important, it should take as input a format string that gives the core of the text to write out, with placeholders for the pieces to be replaced for customization. So, with the format of our address list in mind, let's look at one way to write that input text:

static string formletter =
"To: $1\n"
"Dear $2,\n"
"I'm sure your $5, $4,\n"
"as well as all the other pets in the $3 family,\n"
"will enjoy our latest offering,"
" Universal -Ultra - Mega Vitamins,\n"
"Now available for all kinds of animals,"
" including $5s.\n"
"Don't delay, get some today !\n";

This text removes all the stream inserters and replaces every call to match. str(n) with the text $n. It's much easier to read, but it's not as easy to generate our customized messages: the program has to scan through the entire text, searching for the escape sequences, and replacing them with the corresponding text from the match object. I won't bore you with the details of that code. If you had to, you could write it yourself. But you'll certainly prefer not having to write it. Instead, you can do this, using match_result's template member function format:

Example 20.2. Formatting (regexform/formatting.cpp)

#include <regex>
#include <iostream>
#include <string>
#include <sstream>
using std::tr1::regex; using std::tr1::smatch;
using std::cout; using std::string;
using std::istringstream;

static const string addrlist =
"joebob@notarealaddress.org, Joe, Bob, Bubba, iguana \n"
"missy@notarealaddress.org, Missy, Treadwell,"
     "Reginald Addington Farnsworth II,"
     "prize - winning Toy Poodle \n"
"killer@notarealaddress.org, Spike, Redwood,"
     "Fangs, snake \n"
"kitten@notarealaddress.org, Sally, Smith,"
     "Mr.Bubbles, goldfish \n";

static string formletter =
"To : $1\n"
"Dear $2,\n"
"I ' m sure your $5, $4,\n"
"as well as all the other pets in the $3 family,\n"
"will enjoy our latest offering,"
"Universal -Ultra - Mega Vitamins,\n"
"Now available for all kinds of animals,"
"including $5s.\n"
"Don't delay, get some today !\n";

int main ()
  {
  regex rgx (
    "(.*)[[: space :]]*,[[: space :]]*"
    "(.*)[[: space :]]*,[[: space :]]*"
    "(.*)[[: space :]]*,[[: space :]]*"
    "(.*)[[: space :]]*,[[: space :]]*"
    "(.*)");
  smatch match;
  istringstream addresses (addrlist);
  string address;
  while (getline (addresses, address)
    && regex_match (address, match, rgx))
      {
      string letter = match.format (formletter);
      cout << letter;
      }
  return 0;
  }

This can be written still more simply, using the algorithm regex_replace.

Example 20.3. Replacing (regexform/replacing.cpp)

#include <regex>
#include <iostream>
#include <string>
#include <sstream>
using std::tr1::regex; using std::tr1::regex_replace;
using std::cout; using std::string;
using std::istringstream;

static const string addrlist =
"joebob@notarealaddress.org, Joe, Bob, Bubba, iguana \n"
"missy@notarealaddress.org, Missy, Treadwell,"
  "Reginald Addington Farnsworth II,"
  "prize - winning Toy Poodle \n"
"killer@notarealaddress.org, Spike, Redwood,"
  "Fangs, snake \n"
"kitten@notarealaddress.org, Sally, Smith,"
  "Mr.Bubbles, goldfish \n";

static string formletter =
"To : $1\n"
"Dear $2,\n"
"I 'm sure your $5, $4,\n"
"as well as all the other pets in the $3 family,\n"
"will enjoy our latest offering,"
" Universal -Ultra - Mega Vitamins,\n"
"Now available for all kinds of animals,"
" including $5s.\n"
"Don't delay, get some today !\n";

int main ()
  {
  regex rgx (
    "(.*)[[: space :]]*,[[: space :]]*"
    "(.*)[[: space :]]*,[[: space :]]*"
    "(.*)[[: space :]]*,[[: space :]]*"
    "(.*)[[: space :]]*,[[: space :]]*"
    "(.*)");
  string letter =
    regex_replace (addrlist, rgx, formletter);
  cout << letter;
  return 0;
  }

In this chapter, we look at both of those approaches. We start, in Section 20.1, with the flag values that you can use to control the result. In Section 20.2, we look at the template member function format. In Section 20.3, we look at the algorithm regex_replace.


Section 20.1. Formatting Options

20.1. Formatting Options

namespace regex_constants {
   static const match_flag_type
     format_default,
     format_sed,
     format_no_copy,
     format_first_only;
}

The flag values have the following meanings:

  • format_default:use ECMAScript formatting rules; copy all non-matching text; replace all occurrences of text matching the regular expression.

  • format_sed: use sed formatting rules.

  • format_no_copy: do not copy nonmatching text.

  • format_first_only: replace only the first occurrence of text that matches the regular expression.

The first two flags apply to both the template member function match_results::format and the algorithm regex_replace. The last two are meaningful only for regex_replace; the format member functions will ignore them.

The ECMAScript formatting rules are defined in [Ecm03]; the sed rules, in [Int03c]. The rules define escape sequences and their meanings. When you use these escape sequences in the format string, each escape sequence is replaced by text according to the rules in Table 20.1.

Table 20.1. Format Escape Sequences

ECMAScript Rules

sed Rules

Replacement Text

"$&"

"&"

The character sequence that matched the entire regular expression ([match[0].first, match[0].second));

"$$"

"$"

"\&"

"&"

"$'" (dollar sign followed by back quote)

The character sequence that precedes the subsequence that matched the regular expression ([match.prefix().first, match.prefix().second))

"$'" (dollar sign followed by forward quote)

The character sequence that follows the subsequence that matched the regular expression ([match.suffix().first, match.suffix().second))

"$n"

"\n"

The character sequence that matched the nth capture group ([match[n].first, match[n].second))

"\\n"

"\n"

"$nn"

The character sequence that matched the nnth capture group ([match[nn].first, match[nn].second))


Section 20.2. Formatting Text

20.2. Formatting Text

template <class BidIt, class Alloc>
template <class OutIt>
  OutIt match_results <BidIt, Alloc>::format (
    OutIt out ,
    const string_type & fmt,
    match_flag_type flags = format_default) const;
template < class BidIt, class Alloc>
string_type match_results <BidIt, Alloc>::format (
  const string_type & fmt,
  match_flag_type flags = format_default) const;

The first template member function generates an output sequence by copying the contents of fmt, replacing escape sequences in fmt with the corresponding text. The function then sequentially assigns each character in the output sequence to *out++. It returns the new value of out.

The second member function constructs a string_type object res, calls format(std::back_inserter(res), fmt, flags), and returns res.

We saw the second version of format in one of the examples in the previous section, in the line

string letter = match . format (formletter);

That call used the default flags. To pass a string that uses the sed format escapes instead of the ECMAScript escapes, pass the flag format_sed as the second argument:

string letter = match. format (formletter , format_sed);

The first version of format is more flexible. It takes an output iterator as the target for the output sequence and returns an iterator that points just past the end of the formatted text. The returned iterator can then be used as the target of further assignments, which will append text to the output sequence that format produced.[3]

[3] Of course, you don't have to write obscure code just because you can. This particular example would be much clearer if it simply appended the contents of tail to the string after calling format. But if it did, that it wouldn't use the return value, so it wouldn't be here as an example.

Example 20.4. Using the Returned Iterator (regexform/returned.cpp)

#include <regex>
#include <iostream>
#include <string>
#include <algorithm>
using std::tr1::regex; using std::tr1::smatch;
using std::tr1::regex_search;
using std::string; using std::cout;
using std::copy;

int main ()
  { // demonstrate match_results::format
  string result ("The URL '");
  string tail ("' was found.");
  regex rgx ("http ://([^/: ]+)");
  string text ("The site http :// www.petebecker.com has"
    "  useful information. " );
  smatch match;
  if (regex_search (text , match , rgx))
    { // show result of successful match
    copy(tail. begin (),tail.end () ,
      match.format ( back_inserter (result), "$&"));
    cout << result << '\n';
    }
  return 0;
  }


Section 20.3. Replacing Text

20.3. Replacing Text

template <class OutIt , class BidIt ,
    class RXtraits, class Elem>
  OutIt regex_replace (
    OutIt out , BidIt first , BidIt last ,
    const basic_regex <Elem , RXtraits>& rgx ,
    const basic_string <Elem>& fmt ,
    match_flag_type flags = match_default);
template <class RXtraits , class Elem>
  basic_string <Elem> regex_replace (
    const basic_string <Elem>& str ,
    const basic_regex <Elem , RXtraits>& rgx ,
    const basic_string <Elem>& fmt,
    match_flag_type flags = match_default);

The first algorithm begins by constructing a regex_iterator object iter (first, last, rgx, flags) and using it to split its input range [first, last) into a series of alternating nonmatching and matching subsequences T0M0T1M1...TN-1MN-1TN, where Mn is the nth match detected by the iterator. If no matches are found, T0 is the entire input range and N is 0. If (flags & format_first_only) != 0, only the first match is used, T1 is all the input text that follows the match, and N is 1. The algorithm then generates an output sequence as follows: For each index i in the range [0, N), if (flags & format_no_copy) == 0, the algorithm appends the text in the range Ti to the output sequence; regardless of the value of flags & format_no_copy, it then appends the text generated by a call to match.format(outseq, fmt, flags), where match is the match_results object returned by the iterator object iter for the subsequence Mi, and outseq is an output iterator that points at the current position in the output sequence. Finally, if (flags & format_no_copy) == 0, it appends the text in the range TN to the output sequence. Then it sequentially assigns each character in the output sequence to *out++ and returns the resulting value of out.

The second algorithm constructs a local variable result of type basic_string<Elem> and then calls regex_replace(back_inserter(result), str.begin(), str.end(), rgx, fmt, flags), returning result.

That first description is pretty dense. It has to be, to get the formal requirements right. Informally, the function copies text from the input sequence [first, last) to the output sequence pointed at by out. Whenever it finds text that matches the regular expression rgx, it replaces that text with the output sequence produced by calling match_results::format with the format string fmt. If you pass the flag format_no_copy, it skips the text that doesn't match the regular expression and copies only the output sequences produced by match_results::format. If you pass the flag format_first_only, it looks only for the first match to the regular expression; all the text after that match is either copied without change or ignored, depending on whether you also passed format_no_copy.

For example, to replace every occurrence of the word "Intel" in a text sequence with the word "Microsoft", try this.[4]

[4] That intriguing coinage in the last sentence of the result happened in draft documentation at a company where I worked.

Example 20.5. Basic Search and Replace (regexform/basicrepl.cpp)

#include <regex>
#include <iostream>
#include <string>
using std::tr1::regex; using std::tr1::regex_replace;
using std::cout;
using std::string;

static const string text =
"For some reason , instead of using the name Microsoft ,\n"
"I used the name Intel when I wrote this.Now I need \n"
"to change it , since I wasn ' t talking about Intel ,\n"
"but about Microsoft.Intelligent people like to think \n"
"they don't make such silly mistakes , but sometimes ,\n"
"alas , they do.\n";

int main ()
  { // demonstrate basic search and replace
  regex rgx ("Intel");
  string replacement ("Microsoft");
  string result;
  regex_replace (back_inserter (result),
    text.begin (), text.end (), rgx, replacement);
  cout << result;
  return 0;
  }

To display only text that matches a regular expression, with each match on a separate line, try this.

Example 20.6. Basic Search (regexform/basicsrch.cpp)

#include <regex>
#include <iostream>
#include <string>
using std::tr1::regex; using std::tr1::regex_replace;
using namespace std::tr1::regex_constants;
using std::cout;
using std::string;

static const string text =
"Each morning I check http :// www.nytimes.com and \n"
"http :// www.boston.com for news of what happened \n"
"overnight.I also look at http :// www.tnr.com to\n"
"see any new articles they have posted.";

int main ()
  { // demonstrate basic search
  regex rgx ("http ://([^/: ]+)");
  string replacement ("$&\n");
  string result;
  regex_replace (back_inserter (result) ,
    text.begin () , text.end () ,
    rgx , replacement , format_no_copy);
  cout  << result;
  return 0;
  }

These examples don't take advantage of the iterator that they pass to receive the output sequence. They could just as easily have been written using the second form of regex_replace. To use that function to replace only the first URL in a text sequence, try this.

Example 20.7. Replace First (regexform/basicfirst.cpp)

#include <regex>
#include <iostream>
#include <string>
using std::tr1::regex; using std::tr1::regex_replace;
using namespace std::tr1::regex_constants;
using std::cout;
using std::string;
static const string text =
"Each morning I check http :// www.nytimes.com and \n"
"http :// www.boston.com for news of what happened \n"
"overnight. I also look at http :// www.tnr.com to\n"
"see any new articles they have posted.";

int main ()
  { // demonstrate basic search
  regex rgx ("http ://([^/: ]+)");
  string replacement ("http :// www.wsj.com");
  string result;
  regex_replace (back_inserter (result),
    text.begin (), text.end (),
    rgx, replacement , format_first_only);
  cout << result;
  return 0;
  }


Exercises

Exercise 1

In this exercise, we look at three approaches to displaying the results of regular expression searches. As we've been doing, we'll write each result directly to cout and will then use regex_match::format to insert characters from each match into an output iterator that writes to cout; finally, we'll use regex_replace to manage the search loop for us.

  1. Write a program that searches for text in the form "name: first-name last-name" and inserts the contents of each successful match into cout with the last name first, followed by a comma, followed by the first name.

  2. Write a program that uses a pair of regex_iterator objects to do the search and calls iter->format to write all the desired text to cout. You can use an iterator object ostream_iterator<char> out(cout, "") to insert individual characters into cout.

  3. Write a program that uses regex_replace with the flag format_no_copy to search for matches and write out their contents.

Exercise 2

Write a program that searches for one occurrence of text that matches a hostname[5] and uses regex_match::format to create a string object with an HTML link to that host. For example, the hostname http://www.petebecker.com would be converted to <A HREF="http://www.petebecker.com">http://www.petebecker.com</A>.

[5] See Exercise 2 in Chapter 17 for a suitable regular expression.

Exercise 3

Write a program that copies an input file and replaces every occurence of text that matches a hostname with an HTML link to that host.

Exercise 4

Write a program that searches an input file for text that matches a hostname and for each match writes a line of text with an HTML link to that host into an output file.

Exercise 5

Write a program that searches the standard input for text that matches a hostname and for each match writes a line of text with an HTML link to that host to the standard output.


Chapter 21. Customizing Regular Expressions

"When I use a word," Humpty Dumpty said, in rather a scornful tone, "it means just what I choose it to meanneither more nor less."

Through the Looking-Glass
LEWIS CARROLL

In Chapter 16, we saw that the template basic_regex<Elem> has a second template argument, with a default type regex_traits<Elem>. In this chapter, we look at that parameter in more detail. As a reminder, the declaration of basic_regex looks like this:

    // CLASS TEMPLATE basic_regex
template <class Elem,
    class RXtraits = regex_traits <Elem> >
    class basic_regex;

Each basic_regex object contains an object of type RXtraits, which determines how the basic_regex object interprets some features of the regular expression grammar. The default template, regex_traits<Elem>, is required to work only when Elem is char or wchar_t. If you write your own traits type, you can support additional character types, provide a hook for your own type of locale objects, change the rules for character matching, change the collation rules, and add or remove character classifications. If you're ambitious, you could, for example, add Unicode support to the basic_regex template. Simply pick a suitable character type, such as the up-and-coming char32_t, write a class that provides the necessary traitslet's call it unicode_traitsand then create a regular expression object: basic_regex<char32_t, unicode_-traits>.

The following sections each present a related subset of the requirements for a regular expression traits class. The required elements are presented as code snippets that must be valid for a conforming traits class. The list of elements is followed by a discussion of how the rest of the regular expression library uses these elements, then by the specific choices made in the TR1 library for the required traits types, regex_traits<char> and regex_traits<wchar_t>.

The last section has a synopsis of the class template regex_traits, so that you can see all these elements in one place.

The code snippets use the following names, with their specified meanings:

  • tr: the name of the traits type

  • ctr: a const object of type tr

  • tr: an object of type tr

  • ch: a value of type TR::char_type

  • loc: an object of type tr::locale_type

  • p: a value of type const Tr::char_type*

  • base: one of the values 8, 10, or 16

  • F1, F2: forward iterators that point at characters of type tr::char_type and define the range [F1, F2)


Section 21.1. Character Traits

21.1. Character Traits

  • tr::char_type : a synonym for the type of character that will be used to describe the regular expression.

  • tr:: string_type : a synonym for std::basic_string<char_type>.

  • tr::length (p): returns a value of type std::size_t, which is the smallest non-negative value len such that p[len] == 0. Its time complexity is O(len).

  • ctr. value (ch, base): returns the numeric value represented by the character ch in the given base. If the character ch is not a valid digit in that base, the expression yields -1.

Usage

The static member function length is called whenever the implementation needs to know the length of a null-terminated character string.

The member function value is called whenever the implementation needs to translate a series of digits into a numeric value, that is, when it encounters an OCTAL ESCAPE SEQUENCE, a HEXADECIMAL ESCAPE SEQUENCE, a UNICODE ESCAPE SEQUENCE, or a REPETITION with an explicit count.

Class Template regex_traits Specializations

The class template regex_traits implements length(p) by calling std:: char_traits<Elem>::length(p).

The specialization regex_traits<char> TReats the characters '0' tHRough '7' as octal digits, the characters '0' tHRough '9' as decimal digits, and the characters '0' through '9', 'a' through 'f', and 'A' tHRough 'F' as hexadecimal digits, with their usual meanings. The specialization regex_traits<wchar_t> TReats the wide-character equivalents of those characters in the same way.


Section 21.2. Locales

21.2. Locales

  • tr:: locale_type : a synonym for a copy-constructible type that represents the locale used by the traits class.

  • tr. imbue (loc): copies loc to tr's locale object and makes any other changes needed to use the new locale correctly. It returns a copy of the previous locale object.

  • ctr. getloc (): returns a copy of tr's locale object.

Usage

The class template basic_regex<Elem, RXtraits> has three members that use the locale elements of RXtraits. The nested type name basic_regex<Elem, RXtraits>::locale_type is a synonym for RXtraits::locale_type, and the two member functions basic_regex<Elem, RXtraits>::imbue(loc) and basic_regex<Elem, RXtraits>::getloc() both forward to the corresponding member function of the nested RXtraits object.

Class Template regex_traits Specializations

The class template regex_traits defines the nested type name locale_type to be a synonym for std::locale. Each regex_traits object holds a locale object. The member function getloc() returns a copy of that object. The member function imbue(loc) discards any cached information based on the previous locale, copies loc onto the stored locale object, and returns a copy of the previous locale object.


Section 21.3. Character Matching

21.3. Character Matching

  • ctr. translate (ch): returns a value of type tr::char_type. If two characters ch1 and ch2 are equivalent, ctr.translate(ch1) == ctr. translate(ch2).

  • ctr.translate_nocase (ch): returns a value of type tr::char_type. If two characters ch1 and ch2 are equivalent without regard to case, ctr.translate_nocase(ch1) == ctr.translate_nocase(ch2).

  • ctr. lookup_collatename (F1, F2): returns a TR::string_type object that holds the characters that make up the collating element named by the text sequence pointed at by [F1, F2). If the text sequence does not name a valid collating element, the function returns an empty string.

Usage

Comparing two characters ch1 and ch2 for equality follows these rules.

  • If flags() & regex_constants::icase is nonzero (i.e., the icase flag was passed to the basic_regex object's contructor), ch1 and ch2 are equal if ctr.translate_nocase(ch1) == ctr.translate_-nocase(ch2).

  • Otherwise, if flags() & regex_constants::collate is nonzero (i.e., the collate flag was passed to the basic_regex object's constructor and the icase flag was not), ch1 and ch2 are equal if ctr. translate(ch1) == ctr.translate(ch2).

  • Otherwise, ch1 and ch2 are equal if ch1 == ch2.

Adding a COLLATING SYMBOL to a bracket expression (i.e., "[[.elt.]]") adds the contents of the string object returned by calling ctr.lookup_collate_name with the text between the "[." and ".]" delimiters. If the returned string object is empty (i.e., the text is not the name of a valid collating element), the implementation throws a regex_error object whose code member function returns error_collate.

Class Template regex_traits Specializations

The class template regex_traits implements TRanslate(ch) by returning ch. The template implements TRanslate_nocase(ch) by returning use_-facet<ctype<Elem>>(getloc()).tolower(ch). That is, it uses its current locale to translate the character to lowercase.

The TR1 specification does not impose any testable requirements for regex_traits::lookup_collatename.


Section 21.4. Collating

21.4. Collating

  • ctr. transform (F1, F2): returns a tr::string_type object that can be used as a sort key for the character sequence pointed at by the iterator range [F1,F2). If a character sequence pointed at by the iterator range [G1,G2) should sort before the character sequence pointed at by the iterator range [h1,H2), ctr.transform(G1, G2) <ctr.transform(H1, H2).

  • ctr.transform_primary (F1, F2): returns a tr::string_type object that can be used as a sort key for the character sequence pointed at by the iterator range [F1,F2) without regard to case. If a character sequence pointed at by the iterator range [G1,G2) should sort before the character sequence pointed at by the iterator range [h1,H2), without regard to case, ctr.transform_primary(G1, G2) <ctr.transform_primary(H1, H2).

Usage

The transform function is used to decide whether a character ch0 is in a character range "[ch1 -ch2 ]". It is used as follows.

  • If flags() & regex_constants::collate is false (i.e., the collate flag was not passed to the basic_regex object's contructor), the character is in the range only if ch1 <= ch0 && ch0 <= ch2.

  • Otherwise, the match is determined by first translating each of the three characters ch0, ch1, and ch2 with either ctr.translate_nocase(chx) if flags() & regex_constants::icase is true or with ctr.translate(chx) otherwise, producing ch0a, ch1a, and ch2a, respectively. These three characters are each then converted to TR:: string_type objects str0, str1, and str2, respectively. These three string objects are then transformed into sort keys by calling ctr. transform(strx.begin(), strx.end()), producing str0a, str1a, and str2a. The character ch0 is in the range if str1a <= str0a && str0a <= str2a.

The transform_primary function is used to decide whether a character ch belongs to an EQUIVALENCE CLASS "[[=eq =]]". The equivalence class name is passed to ctr.transform_primary, and the single-character sequence ch is passed to ctr.transform_primary. If the two returned strings compare equal, the character is a member of the equivalence class.

Class Template regex_traits Specializations

The template member function template <class FwdIt> regex_traits<Elem>::transform(FwdIt, FwdIt) constructs a regex_traits<Elem>::string_type object str that holds a copy of the text sequence pointed at by the two iterator arguments. It returns use_facet<collate<Elem> >(getloc()).transform(str.data(), str.data() + str.size()).

The template member function template <class FwdIt> regex_traits <Elem>::transform_primary(FwdIt, FwdIt) returns a case-insensitive version of the sort key returned by regex_traits<Elem>::transform.


Section 21.5. Character Classes

21.5. Character Classes

  • tr:: char_class_type: names an unspecified bitmask type that identifies sets of character classifications.

  • ctr. lookup_classname (F1, F2): returns a value of type tr::char_-class_type that identifies the character classification named by the text sequence pointed at by [F1, F2). If the text sequence does not name a valid character classification, 0 is returned.

  • ctr. isctype (ch, cl): returns true if the character ch is a member of one of the character classifications identified by the tr::char_-class_type value cl; otherwise, false.

Usage

When a regular expression uses a CHARACTER CLASS, the implementation calls lookup_classname with the name of the class. If the function returns 0, it throws a regex_error object whose code member function returns error_ctype. Otherwise, to match a character against that character class, the implementation calls isctype with the character and the value returned by lookup_classname. The character matches only if isctype returns TRue.

Class Template regex_traits Specializations

For regex_traits<char>, the member function lookup_classname treats all the following names and, optionally, more, without regard to case, as valid class names:

  • "d"

  • "s"

  • "w"

  • "alnum"

  • "alpha"

  • "blank"

  • "cntrl"

  • "digit"

  • "graph"

  • "lower"

  • "print"

  • "punct"

  • "space"

  • "upper"

  • "xdigit"

For regex_traits<wchar_t>, the member function lookup_classname does the same, for the wide-character equivalents of these names.

The member function regex_traits::isctype converts its argument cl into a value cl_mask of type std::ctype_base::mask in an unspecified manner and then calls use_facet<ctype<Elem> >(getloc()).is(ch, cl_mask). If the result is TRue, the function returns TRue. Otherwise, if cl has bits set that identify the character class named "w" and ch is '_', the function returns TRue. Otherwise, if cl has bits set that identify the character class named "blank" and ch is in an implementation-defined set of characters for which isspace(ch, getloc()) returns TRue, the function returns true. Otherwise, it returns false.

What that comes down to is that isctype looks to the traits object's current locale for the details of its character classifications. Granted, the mapping to the mask type is unspecified, but no implementer will violate the obvious correspondence. The rest of the paragraph does some fine-tuning. The character class "w"[1] includes underscores. The description of the character class "blank"[2] paraphrases the description of the isblank function that was added to C with C99 and is included in the TR1 library.

[1] And with wide characters, L"w", presumably; this omission seems to be an oversight.

[2] And L"blank".


Section 21.6. The regex_traits Class Template

21.6. The regex_traits Class Template

The class template regex_traits is defined in the header <regex>.

namespace std {   // C++ standard library
  namespace tr1 { // TR1 additions
    // CLASS TEMPLATE regex_traits
template <class Elem>
  struct regex_traits {

    // CHARACTER TRAITS
  typedef Elem  char_type;
  typedef basic_string <Elem> string_type;
  static size_t  length (const char_type *str);
  int value (Elem ch, int base) const;

    // LOCALES
  typedef unspecified locale_type;
  locale_type imbue(locale_type loc);
  locale_type getloc () const;

    // CHARACTER MATCHING
  char_type translate (char_type ch) const;
  char_type translate_nocase (char_type ch) const;
  template<class FwdIt>
    string_type lookup_collatename (
      FwdIt first, FwdIt last) const;

    // COLLATING
  template<class FwdIt>
    string_type transform (
      FwdIt first, FwdIt last) const;
  template<class FwdIt>
    string_type transform_primary (
      FwdIt first, FwdIt last) const;

    // CHARACTER CLASSES
  typedef unspecified char_class_type;
  template<class FwdIt>
    char_class_type lookup_classname (
      FwdIt first, FwdIt last) const;
  bool isctype (char_type ch, char_class_type cls) const;

  };

    // SPECIALIZATIONS OF CLASS TEMPLATE regex_traits
template <>
  struct regex_traits<char>;
template <>
  struct regex_traits<wchar_t>;
} }


Part VII: C Compatibility

    Chapter 22. C Compatibility


Chapter 22. C Compatibility

It were not best that we should all think alike; it is difference of opinion that makes horse-races.

Pudd'nhead Wilson
MARK TWAIN

The original C standard was published in 1990[1] and amended in 1995. The C++ standard, first published in 1998, was based in part on the C language as it existed at the time. The C standard was revised in 1999, but those changes are not reflected in the current C++ standard. The TR1 library picks up the library changes made to C in 1999. In Chapter 12, we looked at those changes as they affect floating-point math. In this chapter, we'll look at the rest of those changes.

[1] Or 1989, depending on which standards organization you're talking about.

Those changes include the addition of library functions that traffic in values of an integer type guaranteed to be at least 64 bits wide (Section 22.2) and the addition of a number of predefined types with specific sizes (Section 22.3). Other changes include additional text conversion functions (Section 22.4), format specifiers (Section 22.5), and additional printf and scanf variants (Section 22.6), as well as a couple of new character classification functions (Section 22.7), and a header for use with Boolean types (Section 22.8). But first, some background.


Section 22.1. Integer Types

22.1. Integer Types

Integer types in C and C++ were originally designed for speed. As a result, the specifications of these types give the minimum range of values that the type must support; implementations are free to provide larger ranges and often do when the hardware that the implementation targets has faster operations for larger types. The type int, in particular, must be able to store values in the range [-32767, 32767], but it also "has the natural size suggested by the architecture of the execution environment."[2] "Natural size" is not a testable requirement. Nevertheless, it's what the C standard requires, [3] and in practice, there is little disagreement over what a compiler should do for a particular hardware system.

[2] [Int99, 6.2.5/4].

[3] The C++ standard uses similar words.

This flexibility is needed because different hardware architectures have different fundamental capabilities. In particular, as system bus widths increase, the natural size of an integer data type also increases. In the 1970s, it made good sense to have an int type that occupied 16 bits and could hold values in the range [-(215- 1),215- 1].[4] By the mid-1990s, smaller hardware systems were still important, but 32-bit architectures dominated the desktop world, and most compilers for these systems provided an int type that could hold values in the range [-(231- 1),231- 1].[5] More recently, 64-bit processors have been coming into the mainstream, and the natural progression would be to an int type that can hold values in the range [-(263- 1),263- 1].[6]

[4] That is, -32767 through 32767.

[5] That is, -2, 147, 483, 647 through 2,147,483,647.

[6] That is, -922337203685... Well, you get the idea.

In practice, that didn't happen. Compilers stuck with 32-bit int types and added new 64-bit integer types with various ugly names. Aside from the ugly names, there is some sound logic to this: A 32-bit integer type is sufficient for almost all integer computations, and 64-bit processors have fast 32-bit math instructions, so it's reasonable to keep the size of an int at 32 bits. That leaves the problem of what to call the new 64-bit type. The natural name for it would be long int, which has a minimum size of 32 bits but, like all integer types, is allowed to be larger. But programmers wanted assurance that the size would be at least 64 bits, so compilers introduced these new types.

In 1999, the C standard followed the industry trend, [7] adding the types long long int and unsigned long long int to the language. The integer types in C and their sizes are listed in Table 22.1. C++ has all but the two variants of long long, and those will almost certainly become part of the language in its next revision.[8] In the meantime, the TR1 library has functions that are intended for use with 64-bit types when you have a compiler that provides them.[9]

[7] Which is what standards are supposed to do, which is why I grudgingly agree that the ugly name long long int ought to be part of the language.

[8] At the time of this writing, the appropriate changes have been approved. It's unlikely that they'll be removed.

[9] It doesn't say that, but it wouldn't bother me a bit if an implementation of the TR1 library documented that it doesn't provide the functions that take 64-bit integer types, because the compiler it's targeting doesn't support them.

Table 22.1. Minimum Ranges of Integer Types

Type

Minimum

Maximum

signed char

-(27 - 1)

27 - 1

unsigned char

0

28 - 1

char

[*]

[*]

short int

-(215 - 1)

215 - 1

unsigned short int

0

216 - 1

int

-(215 - 1)

215 - 1

unsigned int

0

216 - 1

long int

-(231 - 1)

231 - 1

unsigned long int

0

232 - 1

long long int

-(263 - 1)

263 - 1

unsigned long long int

0

264 - 1

[*] The type char must have the same range as either unsigned char or signed char.


Section 22.2. The 64-Bit Integer Types

22.2. The 64-Bit Integer Types

22.2.1. Naming the 64-Bit Types

typedef signed integer type _Longlong;
typedef unsigned integer type _ULonglong;

The first type is a synonym for a signed integer type that occupies at least 64 bits. The second type is a synonym for an unsigned integer type that occupies at least 64 bits.

Any header that uses either of these types provides an idempotent definition for the type or types that it uses.

Various compilers use a couple of different names for 64-bit integer types, so the TR1 library provides these typedefs to mask the differences in the names. As we'll see shortly, the header <cstdlib> uses both of these names, so code that uses the TR1 library to provide 64-bit functions can use that header to ensure that these names are defined. However, these definitions are in the namespace std::tr1. If you use this header, you have to either explicitly qualify the name of the type with its namespace or add a using declaration to hoist the name into the global namespace. Instead of doing that, I suggest using the header <stdlib.h>, which puts the names in the global namespace. You might have an easier transition when these things become part of the C++ standard.

Example 22.1. Using 64-Bit Types (compat/bigtypes.cpp)

#include <stdlib.h>
#include <typeinfo>
#include <iostream>
using std::cout;

int main()
  { // show use of_Longlong and_ULonglong
  _Longlong val = 3;
  _ULonglong uval = 4;
  cout << typeid(val).name() << '\n';
  cout << typeid(uval).name() << '\n';
  return 0;
  }

22.2.2. Value Ranges of the 64-Bit Types

The headers <climits> and <limits.h> define three macros that give the ranges of values that these types can hold.[10]

[10] TR1 does not add a requirement that the template numeric_limits, defined in <limits>, support these types.

#define LLONG_MAX maximum value for _Longlong
#define LLONG_MIN minimum value for _Longlong
#define ULLONG_MAX maximum value for _ULonglong

The first and second macros define compile-time constants giving the maximum and minimum values, respectively, that can be stored in an object of type _Longlong. The third macro defines a compile-time constant giving the maximum value that can be stored in an object of type _ULonglong.

The value of LLONG_MAX must be greater than or equal to 263 1. The value of LLONG_MIN must be less than or equal to (263 1). The value of ULLONG_MAX must be greater than or equal to 264 - 1.

Values of type _Longlong and _Ulonglong can, of course, be inserted into streams

Example 22.2. Value Ranges of 64-Bit Types (compat/values.cpp)

#include <stdlib.h>
#include <iostream>
using std::cout;

int main()
  {   // show range limits
  cout << "_Longlong can hold values in the range\n\t["
     << LLONG_MIN << ',' << LLONG_MAX << "]\n";
  cout << "_ULonglong can hold values in the range\n\t["
    << 0 << ',' << ULLONG_MAX << "]\n";
  return 0;
  }

22.2.3. Additions to the Header <cstdlib>

namespace std {
  namespace tr1 {

    // TYPE lldiv_t
  typedef struct {
  _Longlong quot, rem;
  } lldiv_t;

    // C FUNCTIONS AND C++ OVERLOADS
  _Longlong llabs(_Longlong);
  _Longlong abs(_Longlong)
  lldiv_t lldiv(_Longlong, _Longlong);
  lldiv_t div(_Longlong, _Longlong);

} }

The TR1 library adds one type and several functions to the header <cstdlib>. We look here at that type and at the four functions listed earlier; in Section 22.4, we look at several functions for converting between text sequences and numeric types.

typedef struct {
_Longlong quot, rem;
} lldiv_t;

The type describes an object that can hold the quotient and remainder produced by dividing a value of type _Longlong by a value of type _Longlong. The order of the two members is unspecified.

Yes, its name really does have to be a typedef, because that's the way it's defined in C.

_Longlong llabs(_Longlong val);
_Longlong abs(_Longlong val)

The two functions return the absolute value of their argument.

The first function follows the C convention of prefixing the names of the abs functions with a type marker. The second, available in C++ but not in C, provides an overload of abs, so that the header now supplies three overloads: one for int, one for long int, and one for _Longlong.

lldiv_t lldiv(_Longlong numer, _Longlong denom);
lldiv_t div(_Longlong numer, _Longlong denom);

The two functions return an object that holds the result of dividing numer by denom. The returned object's member quot holds the value numer / denom, and its member rem holds the value numer % denom.

Some systems still do division with code rather in hardware. If integer division is slow and you need both results, this function can speed things up because it has to do the division only once.


Section 22.3. Fixed-Size Integer Types

22.3. Fixed-Size Integer Types

At one time or another, most programmers have needed an integer type with a particular size, usually 8, 16, 32, or 64 bits. It's easy enough to write a macro chain to get the smallest integer type that's at least as large as the size you need, but that's tedious and doesn't scale well; headers from different libraries may well use different names for types that are the same. In C99, the header <stdint.h> provides a large set of typedefs for types with the following properties:

  • Integer types with a specific number of bits

  • Integer types with at least a specific number of bits

  • The fastest integer types with at least a specific number of bits

  • Integer types large enough to hold pointers to objects

  • Integer types with the greatest width

In the TR1 library, the header <cstdint> provides these typedefs in the namespace std::tr1, and the header <stdint.h> provides them in the global namespace. These types are discussed in Section 22.3.1

These headers also provide a set of function-like macros that add the appropriate suffix to a numeric constant value to turn it into a compile-time constant with an integer type with a minimum specified width. In addition, for each of the signed integer types in the TR1 library, two macros give the maximum and minimum values for that type. For each unsigned integer type, one macro gives the maximum value. Further, a handful of macros give the maximum and minimum values for other typedefs from the standard library, such as ptrdiff_t. All these macros are discussed in Section 22.3.2.

The C99 header <inttypes.h> has a handful of function prototypes for functions that take arguments of these types. As always, the TR1 header <cinttypes> puts those prototypes into namespace std::tr1, and the TR1 header <inttypes.h> puts them into the global namespace. We look at some of those functions in Section 22.3.3. The rest are functions that convert between text sequences and numeric values; we look at those, and a bunch of macros that define printf and scanf format specifiers for these types, in Section 22.6.

22.3.1. Type Names in the Header <cstdint>

The types named in the header <cstdint> all include an unsigned decimal number without leading zeros that designates the number of bits that the type is guaranteed to have. Types whose names begin with int are signed integer types; types whose names begin with uint are unsigned integer types. When two names differ only in that one begins with u and the other doesn't, they name corresponding unsigned and signed integer types.[11]

[11] Thus, if int32_t is a synonym for int, uint32_t must be a synonym for unsigned int.

namespace std {
  namespace tr1 {
     // EXACT-WIDTH INTEGER TYPES
   typedef signed integer type int8_t;       // optional
   typedef signed integer type int16_t;      // optional
   typedef signed integer type int32_t;      // optional
   typedef signed integer type int64_t;      // optional
   typedef unsigned integer type uint8_t;    // optional
   typedef unsigned integer type uint16_t;   // optional
   typedef unsigned integer type uint32_t;   // optional
   typedef unsigned integer type uint64_t;   // optional
} }

The types are synonyms for integer types with the exact number of specified bits.

If an implementation has integer types with 8, 16, 32, or 64 bits, it must provide the corresponding exact-width integer types.

Implementations are not required to provide integer types with the usual power-of-2 bit widths. If they do provide any of those types, these typedefs are synonyms for the corresponding types.

namespace std {
  namespace tr1 {
     // MINIMUM-WIDTH INTEGER TYPES
   typedef signed integer type int_least8_t;
   typedef signed integer type int_least16_t;
   typedef signed integer type int_least32_t;
   typedef signed integer type int_least64_t;
   typedef unsigned integer type uint_least8_t;
   typedef unsigned integer type uint_least16_t;
   typedef unsigned integer type uint_least32_t;
   typedef unsigned integer type uint_least64_t;
} }

The types are synonyms for the smallest integer types with at least the number of specified bits.

namespace std {
  namespace tr1 {
     // THE FASTEST INTEGER TYPES WITH AT
     // LEAST A SPECIFIC NUMBER OF BITS
   typedef signed integer type int_fast8_t;
   typedef signed integer type int_fast16_t;
   typedef signed integer type int_fast32_t;
   typedef signed integer type int_fast64_t;
   typedef unsigned integer type uint_fast8_t;
   typedef unsigned integer type uint_fast16_t;
   typedef unsigned integer type uint_fast32_t;
   typedef unsigned integer type uint_fast64_t;
}  }

The types are synonyms for the fastest[12] integer types with at least the number of specified bits.

[12] Whatever that means. In fact, the C99 standard acknowledges that the designated type need not be fastest for all purposes.

namespace std {
  namespace tr1 {
     // INTEGER TYPES LARGE ENOUGH TO
     // HOLD POINTERS TO OBJECTS
   typedef signed integer type intptr_t;
   typedef unsigned integer type uintptr_t;
}  }

The types are synonyms for an integer type that is wide enough to hold a void*, suitably converted, so that its value can be converted back to a void* to produce a value that compares equal to the original value.

These types are optional.

The old C trick of converting a pointer into an int value and then converting it back worked only if an int could hold all the possible values of a pointer. Sometimes, pointers are bigger than integers, though, and this trick doesn't work. If these two types are present, you can use them, and the round-trip conversion will work.

Example 22.3. Pointer-to-Integer Conversions (compat/ptoi.cpp)

#include <cstdint>
#include <iostream>
#include <iomanip>
using std::cout; using std::hex; using std::boolalpha;

int main()
  {   // demonstrate intptr_t, uintptr_t
  int i;
  int *ip = &i;
  intptr_t intptr = (intptr_t)ip;
  uintptr_t uintptr = (uintptr_t)ip;
  cout << boolalpha;
  cout << "address:  " << (void*)ip << '\n';
  cout << "intptr:   " << hex << intptr << '\n';
  cout << "uintptr:  " << hex << uintptr << '\n';
  cout << "ip == (int*)intptr:  "
    << (ip == (int*)intptr) << '\n';
  cout << "ip == (int*)uintptr:"
    << (ip == (int*)uintptr) << '\n';
  return 0;
  }

namespace std {
  namespace tr1 {
     // INTEGER TYPES WITH THE GREATEST WIDTH
     typedef signed integer type intmax_t;
     typedef unsigned integer type uintmax_t;
} }

The types are synonyms for types that can represent any value of any signed or unsigned integer type, respectively.

22.3.2. Macros in the Header <cstdint>

Descriptions of the macros for creating integer constants are in Table 22.2; descriptions of the macros that give minimum and maximum possible values and the minimum required ranges for types defined in C99 are in Table 22.3; descriptions for types defined in C90 are in Table 22.4. The names of the macros that create typed integer constants include a decimal number that gives the minimum number of bits in the resulting value. This number must be the same as the number in one of the int_least N _t types that the implementation provides.

Table 22.2. Function-like Macros for Creating Typed Constants

Macro Name

Type

INT N_C(value)

int_least N_t

UINT N_C(value)

uint_least N_t

Table 22.3. Minimum Ranges for C99 Types

Macro Name

Type

Required Value

INT N _MIN

int N _t

-(2N-1)

INT N _MAX

int N _t

2N-1 - 1

UINT N _MAX

uint N _t

2N - 1

INT_LEAST N _MIN

int_least N _t

-(2N-1 - 1)

INT_LEAST N _MAX

int_least N _t

2N-1 - 1

UINT_LEAST N _MAX

uint_least N _t

2N - 1

INT_FAST N _MIN

int_fast N _t

(2N-1 - 1)

INT_FAST N _MAX

int_fast N _t

2N-1 - 1

UINT_FAST N _MAX

uint_fast N _t

2N - 1

INTPTR_MIN

intptr_t

(215 - 1)

INTPTR_MAX

intptr_t

215 - 1

UINTPTR_MAX

uintptr_t

216 - 1

INTMAX_MIN

intmax_t

(263 - 1)

INTMAX_MAX

intmax_t

263 - 1

UINTMAX_MAX

uintmax_t

264 - 1

Table 22.4. Minimum Ranges for C90 Types

Macro Name

Type

Required Value

PTRDIFF_MIN

ptrdiff_t

65535

PTRDIFF_MAX

ptrdiff_t

65535

SIZE_MAX

size_t

65535

SIG_ATOMIC_MIN

sig_atomic_t (if signed)

-127

SIG_ATOMIC_MAX

sig_atomic_t (if signed)

127

SIG_ATOMIC_MIN

sig_atomic_t (if unsigned)

0

SIG_ATOMIC_MAX

sig_atomic_t (if unsigned)

255

WCHAR_MIN

wchar_t (if signed)

127

WCHAR_MAX

wchar_t (if signed)

127

WCHAR_MIN

wchar_t (if unsigned)

0

WCHAR_MAX

wchar_t (if unsigned)

255

WINT_MIN

wint_t (if signed)

32767

WINT_MAX

wint_t (if signed)

32767

WINT_MIN

wint_t (if unsigned)

0

WINT_MAX

wint_t (if unsigned)

65535

22.3.3. The Header <cinttypes>

namespace std {
  namespace tr1 {

     // TYPE imaxdiv_t
   typedef struct {
   intmax_t quot, rem;
   } imaxdiv_t;

     // C FUNCTIONS AND C++ OVERLOADS
   intmax_t imaxabs(intmax_t);
   intmax_t abs(intmax_t)
   imaxdiv_t imaxdiv(intmax_t, intmax_t);
   imaxdiv_t div(intmax_t, intmax_t);

} }

The C99 header <inttypes.h> provides one type and several functions. The TR1 header <cinttypes> puts these names in the namespace std::tr1. The TR1 header <stdint.h> puts them in the global namespace.

We look here at that type and at the four functions listed previously; in Section 22.4, we look at several functions for converting between text sequences and numeric types.

typedef struct {
intmax_t quot, rem;
} imaxdiv_t;

The type describes an object that can hold the quotient and remainder produced by dividing a value of type intmax_t by a value of type intmax_t. The order of the two members is unspecified.

intmax_t imaxabs(intmax_t val);
intmax_t abs(intmax_t val)

The two functions return the absolute value of their argument.

imaxdiv_t imaxdiv(intmax_t numer,intmax_t denom);
imaxdiv_t div(intmax_t numer,intmax_t denom);

The two functions return an object that holds the result of dividing numer by denom. The returned object's member quot holds the value numer/denom, and its member rem holds the value numer % denom.


Section 22.4. Text Conversions

22.4. Text Conversions

The C99 Standard provides a set of functions for converting arrays of char and arrays of wchar_t to numeric values of various types. The names and return types of these functions are given in Table 22.5. The ones that are new in C99 are marked with an asterisk.

Table 22.5. Text-Conversion Functions for Character Arrays

Function Name

Function Name

Return Type

strtof*

wcstof*

float

strtod

wcstod

double

strtold*

wcstold*

long double

strtol

wcstol

long int

strtoul

wcstoul

unsigned long int

strtoll*

wcstoll*

_Longlong

strtoull*

wcstoull*

_ULonglong

strtoimax*

wcstoimax*

intmax_t

strtoumax*

wcstoumax*

uintmax_t

Declarations of the functions in the last two rows are in the header <cint-types>. For the rest, declarations of the strXXX functions are in the header <cstdlib>, and of the wcsXXX functions, the header <cwchar>.

These functions all have similar signatures, differing in the character type that they take and the numeric type that they return. When the name begins with str, the function's character type is char; when it begins with wcs, the character type is wchar_t. If we represent the character type by Elem and the return type by Ret, the signatures of all these functions look like this:

   // INTEGER CONVERSIONS:
Ret xxxtoRet(const Elem *s,Elem **endptr,int base);
   // FLOATING-POINT CONVERSIONS:
Ret xxxtoRet(const Elem *s,Elem ** endptr);

Each of these text-conversion functions converts the initial sequence of characters in the string s to an equivalent value x of type Ret. If endptr is not a null pointer, the function stores a pointer to the unconverted remainder of the string in *endptr. The function then returns x. If the string does not match a valid pattern, the value of x is 0, and the value, if any, stored in *endptr is s.

When the return type is an integer type, the conversion is done in the base indicated by the argument base. If the equivalent value is too large to represent as type Ret, the function stores the value of ERANGE in errno and returns either the maximum value that can be represented by the type Ret if x is positive or the minimum value if x is negative.

When the return type is a floating-point type, the conversion is done in base 10. If a range error occurs, the functions behave as described in Section 12.5.


Section 22.5. Format Specifiers

22.5. Format Specifiers

22.5.1. The Header <cinttypes>

namespace std {
  namespace tr1 {
      // MACROS
   PRIxxx
   SCNxxx
} }

The macros each expand to a string literal that holds a format specifier for one of the C99 typedefs. The macro names have one of the forms

PRIFSN
PRIFT
SCNFSN
SCNFT

where F is replaced by one of d, i, o, u, x, X; S is replaced by FAST or by LEAST or by nothing; N is replaced by an unsigned decimal number; and T is replaced by MAX or PTR.

The macros whose names begin with PRI are format specifiers for printf. The macros whose names begin with SCN are format specifiers for scanf.

The character designated by F is the desired format specifier.

The replacements for S and N come from the name of the type to be translated, either int_SN _t or uint_SN _t.

When the replacement for T is MAX, the value is of type intmax_t or uintmax_t. When the replacement for T is PTR, the value is of type intptr_t or uintptr_t.

For example, to use printf to write a value of type int_least16_t as a signed decimal value, use the format specifier PRIdLEAST16. To use scanf to read a value of type uint_fast8_t written as a hexadecimal integer value, use the format specifier SCNxFAST8.

Because they're string literals, these macros aren't as easy to use as ordinary format specifiers. To write a string literal that uses one of these macros you have to rely on string concatenation.

int_least16_t x = 3;
printf("The value is: " PRIdLEAST16 "\n" , x);

If the underlying type for int_least16_t is unsigned int, the macro could expand to "%u".

int_least16_t x = 3;
printf("The value is:" "\%u" "\n",x);

The compiler will concatenate the three string literals, producing the format string that will be passed to printf.

int_least16_t x = 3;
printf("The value is: \%u\n",x);

22.5.2. Additional Format Specifiers

The C99 standard adds several format specifiers for the function strftime. C99 also adds a couple of format specifiers for the printf and scanf families of functions to support writing and reading floating-point values in hexadecimal format as well as several length modifiers to indicate which integer type a format flag refers to.

strftime

The function strftime converts date information stored in an object of type struct tm into text described by a format string. In the C99 standard, its prototype is in the header <time.h>. In C++, as usual, it is declared in namespace std in the header <ctime> and in the global namespace in the header <time.h>.

namespace std {

  size_t strftime(char *s,size_t n,
    const char *fmt,const struct tm *tptr);

}

The function generates formatted text, under the control of the format fmt and the values stored in *tptr. The generated characters are stored in successive locations of the array object of size n whose first element has the address s. The function then stores a null character in the next location of the array. The function returns x, the number of characters generated, if x < n; otherwise, it returns 0, and the values stored in the array are indeterminate.

For each multibyte character other than % in the format, the function stores that multibyte character in the array object. Each occurrence of % followed by an optional qualifier and another character in the format is a conversion specifier. The optional qualifiers, added with C99, are

  • E, to represent times in terms of a locale-specific era, such as 1 BC instead of 0000

  • O, to represent numeric values with a set of locale-specific alternative digits, such as first instead of 1

For each conversion specifier, the function stores a replacement-character sequence. The following list gives all the conversion specifiers for strftime, with the fields in *tptr that they use, a brief description of the replacement text, and an example replacement-character sequence in parentheses after the description. All the examples are for the "C" locale, which ignores any optional qualifier. They use the date and time Sunday, 2 December 1979, at 06:55:15 AM EST. Conversion specifiers marked with a + rather than a bullet are new with C99.

For a Sunday week of the year, week 1 begins with the first Sunday on or after 1 January. For a Monday week of the year, week 1 begins with the first Monday on or after 1 January. An ISO 8601 week of the year is the same as a Monday week of the year, except as follows.

  • If 1 January is a Tuesday, Wednesday, or Thursday, the week number is one greater. Moreover, days back to and including the immediately preceding Monday in the preceding year are included in week 1 of the current year.

  • If 1 January is a Friday, Saturday, or Sunday, days up to but not including the immediately following Monday in the current year are included in the last week (52 or 53) of the preceding year.

  • %a: (tm_wday), abbreviated weekday name (Sun)

  • %A: (tm_wday), full weekday name (Sunday)

  • %b: (tm_mon), abbreviated month name (Dec)

  • %B: (tm_mon), full month name (December)

  • %c: ([all]), date and time (Sun Dec 2 06:55:15)

  • %Ec: ([all]), era-specific date and time

  • %C: (tm_year), year/100 (19)

  • %EC: (tm_mday, tm_mon, tm_year) era-specific era name

  • %d: (tm_day), day of the month (02)

  • %D: (tm_mday, tm_mon, tm_year), month/day/year from 01/01/00 (12/02/79)

  • %e: (tm_mday), day of the month, leading space for zero ( 2)

  • %F: (tm_mday, tm_mon, tm_year), year-month-day (1979-12-02)

  • %g: (tm_wday, tm_yday, tm_year), year for ISO 8601 week, from 00 (79)

  • %G: (tm_wday, tm_yday, tm_year), year for ISO 8601 week, from 0000 (1979)

  • %h: (tm_mon), same as %b (Dec)

  • %H: (tm_hour), hour of the 24-hour day, from 00 (06)

  • %I: (tm_hour), hour of the 12-hour day, from 01 (06)

  • %j: (tm_yday), day of the year, from 001 (336)

  • %m: (tm_mon), month of the year, from 01 (12)

  • %M: (tm_min), minutes after the hour (55)

  • %n: newline character '\n'

  • %p: (tm_hour), AM/PM indicator (AM)

  • %r: (tm_sec, tm_min, tm_hour), 12-hour time, from 01:00:00 AM (06:55:15 AM)

  • %Er:(tm_sec, tm_min, tm_hour, tm_mday), (mon, tm_year), era-specific date and 12-hour time

  • %R: (tm_min, tm_hour), hour:minute, from 01:00 (06:55)

  • %S: (tm_sec), seconds after the minute (15)

  • %t: horizontal tab character '\t'

  • %T:(tm_sec, tm_min, tm_hour), 24-hour time, from 00:00:00 (06:55:15)

  • %u: (tm_wday), ISO 8601 day of the week, to 7 for Sunday (7)

  • %U: (tm_wday, tm_yday), Sunday week of the year, from 00 (48)

  • %V: (tm_wday, tm_yday, tm_year), ISO 8601 week of the year, from 01 (48)

  • %w: (tm_wday), day of the week, from 0 for Sunday (0)

  • %W: (tm_wday, tm_yday), Monday week of the year, from 00 (48)

  • %x: ([all]), date (02/12/79)

  • %Ex: ([all]), era-specific date

  • %X: ([all]), time, from 00:00:00 (06:55:15)

  • %EX: ([all]), era-specific time

  • %y: (tm_year), year of the century, from 00 (79)

  • %Ey: (tm_mday, tm_mon, tm_year), year of the era

  • %Y: (tm_year), year (1979)

  • %FY: (tm_mday, tm_mon, tm_year), era-specific era name and year of the era

  • %z: (tm_isdst), time zone (hours*100 + minutes), if any (-0500)

  • %Z: (tm_isdst), time zone name, if any (EST)

  • %%: percent character '%'

printf

The new format specifiers for the printf functions are

  • %a: write the value of the corresponding argument in hexadecimal

  • %A: write the value of the corresponding argument in hexadecimal except that all alphabetic characters are written in uppercase

  • %F: the same as %f except that all alphabetic characters are written in uppercase

The %a format specifier converts values of type double. When values of type float are passed to printf, they are promoted to double, so you can use %a for float values as well. For values of type long double, use %La.

To write a value in hexadecimal, the value is converted to a text sequence of the form [-] 0x h.hhhh p±d. For a normalized floating-point number, one nonzero hexadecimal digit is to the left of the decimal point; otherwise, the number and values of the hexadecimal digits to the left of the decimal point are unspecified. The number of hexadecimal digits to the right of the decimal point is equal to the precision. If the precision field is not present and FLT_RADIX is a power of 2, the precision is large enough to uniquely represent the value. If the precision field is not present and FLT_RADIX is not a power of 2, the precision is large enough to distinguish all values of type double, although for any particular value, trailing zeros may be left out. If the precision is 0 and the # flag is not present, the decimal-point character is not shown. The exponent represents the decimal exponent of 2 and always has at least one digit. It does not have any leading zeros, unless the value is 0, in which case the exponent is also 0.

In addition to these three format specifiers, the C99 standard adds five length modifiers that can be applied to any of the integer-format specifiers d, i, o, u, x, X and to the character-count format specifier n.[13]

[13] The n specifier takes the address of an integer variable and stores the number of characters written so far into the variable that it points at.

  • hh: the value should be treated as a signed or unsigned char.

  • ll: the value has type _Longlong.

  • j: the value has type intmax_t or uintmax_t.

  • t: the value has type ptrdiff_t.

  • z: the value has type size_t.

The first one gets around complications introduced by the default promotion rules that are used when the corresponding argument is passed to printf. Because they don't have explicit types in the function's prototype, arguments of type char, unsigned char, and signed char are promoted to int or, possibly, unsigned int. The hh length modifier tells the formatting code to undo whatever changes this promotion might have made.[14]

[14] The h length modifier, which was part of the C standard before C99, does the same thing for arguments of type signed short and unsigned short.

For example, to write unsigned values in hexadecimal, use the following format specifiers:

  • "%hhx": value of type unsigned char

  • "%hx": value of type unsigned short

  • "%x": value of type unsigned int

  • "%lx": value of type unsigned long

  • "%llx": value of type _ULonglong

  • "%jx": value of type uintmax_t

  • "%zx": value of type size_t

scanf

All the preceding format specifiers and length modifiers can also be used in the format specifier in a call to any member of the scanf family of functions, with the obvious meanings. Keep in mind, though, that format specifiers for the scanf functions don't say much about the input format. They give the type of the target variable, and they can specify the maximum number of characters to read. Beyond that, they defer to the functions strtol, strtod, and their variants to convert the input text. These functions, in turn, convert from any of the standard output formats. So you can use %e, for example, to read data written with %a, and vice versa.

22.5.3. The hexfloat Manipulator

As we saw in the previous section, C99 adds format specifiers to printf that convert floating-point values to a hexadecimal representation. The TR1 library adds the same capability to iostreams by adding a stream manipulator hexfloat. The manipulator takes advantage of the fact that the combination of flags ios_base::fixed | ios_base::scientific currently has no meaning. The manipulator sets these flags. For a stream inserter, this combination means that floating-point values should be written in hexadecimal. Stream extractors parse all the standard output formats, so there is no need to use a manipulator to read values that have been written in hexadecimal.

Formally, the rule for inserters is described by adding two lines to the table that gives the requirements for floating-point conversions on output, to require that when floatfield has the value ios_base::fixed | ios_base::scientific and uppercase is false, the translation uses the %a format specifier; if uppercase is true and the other two flags are set, the translation uses the %A format specifier.

The manipulator hexfloat is defined in the header <ios>.

namespace std {
  namespace tr1 {

     // C++ FUNCTION
   ios_base& hexfloat(ios_base & str);

} }

The function calls str.setf(ios_base::fixed | ios_base::scientific, ios_base::floatfield) and returns str.

This function acts just like any other stream manipulator: You insert it into an output stream or extract it from an input stream. After that, floating-point values will be written in hexadecimal.

Example 22.4. Hexadecimal Floating-Point Values (compat/hexfloat.cpp)

#include <iostream>
#include <sstream>
#include <iomanip>
using std::boolalpha;
using std::stringstream;
using std::cout; using std::hexfloat;

int main()
  { // demonstrate use of hexfloat stream manipulator
  cout << boolalpha;
  stringstream str;
  double d = 0.1/0.3;
  str << d;
  double res = 0.0;
  str >> res;
  cout << hexfloat << d << ' ' << res
    << (d == res ? " " : " not ") << "equal " << '\n';
  str.clear();
  str << hexfloat << d;
  res = 0.0;
  str >>  res;
  cout << hexfloat << d <<.' ' << res
     << (d == res ? " " : " not ") << "equal " << '\n';
  return 0;
  }


Section 22.6. Formatted I/O

22.6. Formatted I/O

22.6.1. Variable-Length Argument Lists

Most programmers were introduced to variable-length argument lists when they learned the wonders of printf. The prototype for printf looks like this:

int printf(const char *fmt, ...);

The ellipsis at the end of the prototype says that the function takes an unspecified number of arguments of unspecified types in addition to the required argument fmt. As we all know, printf copies the contents of fmt to stdout, replacing each printf conversion specifier in fmt with text representing the value of the corresponding additional argument.[15]

[15] You get extra credit if you know what the value returned by printf means.

Many programmers fall down, however, if they have to write their own function that takes a variable-length argument list and pass that list to another function that takes a variable-length argument list. For example, suppose that you need to write a function that takes the name of a log file, a format specifier, and a variable-length argument list holding values to be logged. The function should use fopen to open the file, pass the resulting FILE* and the format specifier and the additional arguments to fprintf to write the information to the log file, and, when fprintf returns, close the log file. For most programmers, the first attempt at writing this function looks something like this:

   int logdata(const char *fname, const char *fmt , ...)
{
FILE *fp = fopen(fname,"w");
 // how the hell do I call fprintf?
fclose(fp);
return ?;
}

The answer to the question in the comment is that you can't call fprintf with the additional arguments. Instead, you need to use vfprintf, which is just like fprintf but takes a final argument of type va_list instead of an ellipsis. The argument of type va_list, in turn, points at the additional arguments in the call to log.

Example 22.5. Using va_list (compat/valist.c)

#include <stdio.h>
#include <stdarg.h>

int logdata(const char *fname,const char *fmt,...)
{   // log formatted data to file fname
int res = -1;
FILE *fp = fopen(fname,"a");
if (fp)
  { // set up argument list, call vfprintf
  va_list ap;
  va_start(ap,fmt);
  res = vfprintf(fp,fmt,ap);
  fclose(fp);
  va_end(ap);

  }
return res;
}

int main()
  {   // demonstrate use of variable-length argument lists
  FILE  *fp;
  char buf[128];
  logdata("test.txt","%d\n",3);
  logdata("test.txt","%d %d %d\n",3,4,5);
  fp = fopen("test.txt","r");
  while(fgets(buf,sizeof(buf),fp))
    printf(buf);
  fclose(fp);
  return 0;
  }

Of course, in order to do that with the rest of the printf and scanf family, you need versions of those functions that take a final argument of type va_list. Several of these in the C90 standard, but there were quite a few that were missing. The C99 standard fills in these gaps, as we see in Section 22.6.3.

22.6.2. Copying Variable-Length Argument Lists

If you write code that uses variable-length argument lists, you might occasionally need to copy the object that holds the context information for the variable-length argument list. Prior to C99, that was a problem because there are no constraints on the type of that object. On some implementations, it's an array, and arrays can't be copied directly. The solution to this problem in C99 was to add a macro, va_copy, in the header <stdarg.h>. tr1 does the same, adding the macro to both the header <cstdarg> and the header <stdarg.h>.

#define va_copy(dst,src) <void expression>

The arguments dst and src must be objects of type va_list. The macro copies the context information in src to the object designated by dst.

22.6.3. The printf and scanf Functions

Table 22.6 shows the names of all of the printf and scanf variants defined in C99. The ones that are new in C99 are marked with an asterisk. The functions in the second and fourth columns take a final argument of type va_list; the ones in the first and third columns take an arbitrary number of arguments of more or less arbitrary types. Functions in the first and second columns take string arguments of type char_t*; those in the third and fourth columns take wchar_t*.

Table 22.6. printf and scanf Functions

<stdio.h>

<wchar.h>

printf

vprintf

wprintf

vwprintf

fprintf

vfprintf

fwprintf

vfwprintf

sprintf

vsprintf

swprintf

vswprintf

snprintf*

vsnprintf*

scanf

vscanf*

wscanf

vwscanf*

fscanf

vfscanf*

fwscanf

vfwscanf*

sscanf

vsscanf*

swscanf

vswscanf*

The functions in the first row write formatted text to standard output. The functions in the second row write to a file, identified by an initial argument of type FILE*. The functions in the third row write to a character array, identified by an initial argument of type char* or wchar_t*. The functions in the fourth row also write to a character array but take an additional argument that gives the maximum number of charactersincluding the terminating null characterto write. Similarly, the functions in the fifth row read from standard input, those in the sixth row read from a file, and those in the last row read from a character array.


Section 22.7. Character Classification

22.7. Character Classification

      // HEADER <cctype>
namespace std {
  namespace tr1 {

  int isblank(int);
} }
    // HEADER <cwctype>
namespace std {
  namespace tr1 {

  int iswblank(wint_t);

} }

Each function returns true if its argument is one of the standard blank charactersspace and horizontal tab (i.e., ' ' and '\t' for isblank, L' ' and L'\t' for iswblankor if it is one of a locale-specific set of characters that are used to separate words in a line of text, in which case, isspace or iswspace, respectively, must also return true.


Section 22.8. Boolean Type

22.8. Boolean Type

The headers <cstdbool> and <stdbool.h> both define a macro:

#define __bool_true_false_are_defined 1

C99 has a built-in type, _Bool, that holds Boolean values. The header <stdbool.h> defines a macro bool that expands to _Bool and the macros true and false that expand to 1 and 0, respectively. That header also defines a macro __bool_true_false_are_defined that expands to 1, so that source code can test whether those macros are defined. Since C++ has bool as a built-in type and the names true and false as keywords, these macros are not needed. However, in C++, the two headers define __bool_true_false_are_defined, so that C code that tests this macro to see whether these names are defined will get the right answer.


Exercises

Exercise 1

Write a program that shows the minimum and maximum values that can be stored in an object of type _Longlong and the maximum value that can be stored in an object of type _ULonglong.

Exercise 2

Use function overloading to determine the type of each of the following typedefs on your system: int32_t, uint_least32_t, uint_fast8_t, intptr_t, uintptr_t, intmax_t, and uintmax_t.

Exercise 3

For each of the typedefs in the preceding exercise, create a constant of that type with the value 1 and show its value, using printf and a suitable format specifier. Verify that the constant's type is the same as the type named by the typedef.

Exercise 4

For each of the typedefs in the preceding exercise, show the minimum and maximum values that can be stored in an object of that type.


Appendixes

    Appendix A. Headers

    Appendix B. Utility Headers

    Appendix C. Multithreading

    Bibliography


Appendix A. Headers

This appendix presents a synopsis of the TR1 library headers <regex> (Section A.1), <unordered_set> (Section A.2), and <unordered_-map> (Section A.3), and of each of the headers from the standard C++ library that has been extended by the TR1 library: <float.h> (Section A.4), <math.h> (Section A.5), <functional> (Section A.6), <memory> (Section A.7), and <utility> (Section A.8).


Section A.1. Header <regex> Synopsis

A.1. Header <regex> Synopsis

namespace std { // C++ standard library
 namespace tr1 { // TR1 additions

    // CLASS TEMPLATE regex_traits AND basic_regex
template <class Elem>
  struct regex_traits ;
template <>
  struct regex_traits <char>;
template <>
  struct regex_traits <wchar_t>;
template <class Elem,
  class RXtraits = regex_traits <Elem>,
  class basic_regex;
typedef basic_regex <char> regex;
typedef basic_regex <wchar_t> wregex ;

    // CLASS TEMPLATE sub_match
template <class BidIt>
  class sub_match ;
typedef sub_match <const char*> csub_match;
typedef sub_match <const wchar_t *> wcsub_match;
typedef sub_match <string :: const_iterator> ssub_match;
typedef sub_match <wstring :: const_iterator> wssub_match;

    // CLASS TEMPLATE match_results
template <class BidIt,
  class Alloc = allocator <
    typename iterator_traits <BidIt>:: value_type> >
  class match_results ;
typedef match_results <const char*> cmatch ;
typedef match_results <const wchar_t *> wcmatch ;
typedef match_results <string :: const_iterator> smatch ;
typedef match_results <wstring :: const_iterator> wsmatch ;

    // NAMESPACE regex_constants
namespace regex_constants {
  typedef T1 syntax_option_type ;
  static const syntax_option_type
    awk, basic, collate, ECMAScript, egrep,
    extended, grep, icase, nosubs, optimize ;
  typedef T2 match_flag_type ;
  static const match_flag_type match_any, match_default,
    match_not_bol, match_not_bow, match_continuous,
    match_not_eol, match_not_eow, match_not_null,
    match_prev_avail ;
  typedef T3 error_type;
  static const error_type error_badbrace, error_badrepeat,
    error_brace, error_brack, error_collate,
    error_complexity, error_ctype, error_escape,
    error_paren, error_range, error_space, error_stack,
    error_backref ;
  }

    // CLASS regex_error
class regex_error;

    // FUNCTION TEMPLATE regex_match
template <class BidIt, class Alloc, class Elem,
  class RXtraits>
    bool regex_match(BidIt first, Bidit last,
      match_results <BidIt, Alloc>&,
      const basic_regex <Elem, RXtraits>&,
      match_flag_types = match_default);
template <class BidIt, class Elem, class RXtraits>
  bool regex_match(BidIt first, Bidit last,
    const basic_regex <Elem, RXtraits>&,
    match_flag_types = match_default);

template <class Elem, class Alloc, class RXtraits>
  bool regex_match(const Elem*,
    match_results <const Elem*, Alloc>&,
    const basic_regex <Elem, RXtraits>&,
    match_flag_types = match_default);
template <class Elem, class RXtraits>
  bool regex_match(const Elem*,
    const basic_regex <Elem, RXtraits>&,
    match_flag_types = match_default);

template <class IOtraits, class IOalloc,
  class Alloc, class Elem, class RXtraits>
  bool regex_match(
    const basic_string <Elem, IOtraits, IOalloc>&,
    match_results <typename
      basic_string <
        Elem, IOtraits, IOalloc>:: const_iterator,
        Alloc>&,
    const basic_regex <Elem, RXtraits>&,
    match_flag_types = match_default);
template <class IOtraits, class IOalloc,
  class Alloc, class Elem, class RXtraits>
  bool regex_match(
    const basic_string <Elem, IOtraits, IOalloc>&,
    const basic_regex <Elem, RXtraits>&,
    match_flag_types = match_default);

    // FUNCTION TEMPLATE regex_search
template <class BidIt, class Alloc,
  class Elem, class RXtraits>
  bool regex_search(BidIt first, Bidit last,
    match_results <BidIt, Alloc>&,
    const basic_regex <Elem, RXtraits>&,
    match_flag_types = match_default);
template <class BidIt, class Elem, class RXtraits>
  bool regex_search(BidIt first, Bidit last,
    const basic_regex <Elem, RXtraits>&,
    match_flag_types = match_default);

template <class Elem, class Alloc, class RXtraits>
  bool regex_search(const Elem*,
    match_results <const Elem*, Alloc>&,
    const basic_regex <Elem, RXtraits>&,
    match_flag_types = match_default);
template <class Elem, class RXtraits>
  bool regex_search(const Elem*,
  const basic_regex <Elem, RXtraits>&,
  match_flag_types = match_default);

template <class IOtraits, class IOalloc,
  class Alloc, class Elem, class RXtraits>
  bool regex_search(
    const basic_string <Elem , IOtraits , IOalloc>& ,
    match_results <typename
      basic_string <
        Elem, IOtraits, IOalloc>:: const_iterator ,
        Alloc>&,
    const basic_regex <Elem, RXtraits>& ,
    match_flag_types = match_default);
template <class IOtraits, class IOalloc ,
  class Alloc, class Elem, class RXtraits>
  bool regex_search(
    const basic_string <Elem , IOtraits , IOalloc>& ,
    const basic_regex <Elem , RXtraits>& ,
    match_flag_types = match_default);

    // FUNCTION TEMPLATE regex_replace
template <class OutIt, class BidIt,
  class RXtraits, class Elem>
  OutIt regex_replace (OutIt out , BidIt first , BidIt last ,
    const basic_regex <Elem , RXtraits>& ,
    const basic_string <Elem>& fmt ,
    match_flag_type flags = match_default);
template <class RXtraits , class Elem>
  basic_string <Elem> regex_replace (
    const basic_string <Elem>&,
    const basic_regex <Elem, RXtraits>&,
    const basic_string <Elem>& fmt,
    match_flag_type flags = match_default);

    // REGULAR EXPRESSION ITERATORS
template <class BidIt,
  class Elem = iterator_traits <BidIt>:: value_type,
  class RXtraits = regex_traits <Elem>>
    class regex_iterator ;
typedef regex_iterator <const char*> cregex_iterator ;
typedef regex_iterator <const wchar_t *> wcregex_iterator ;
typedef regex_iterator <string :: const_iterator>
  sregex_iterator ;
typedef regex_iterator <wstring :: const_iterator>
  wsregex_iterator ;
template <class BidIt, class Elem =
  iterator_traits <BidIt>:: value_type,
  class RXtraits = regex_traits <Elem>>
    class regex_token_iterator ;
typedef regex_token_iterator <const char*>
  cregex_token_iterator ;
typedef regex_token_iterator <const wchar_t *>
  wcregex_token_iterator ;
typedef regex_token_iterator <string :: const_iterator>
  sregex_token_iterator ;
typedef regex_token_iterator <wstring :: const_iterator>
  wsregex_token_iterator ;

    // STREAM INSERTER
template <class Elem, class IOtraits,
  class Alloc, class BidIt>
  basic_ostream <Elem, IOtraits>&
  operator <<( basic_ostream <Elem, IOtraits>&,
    const sub_match <BidIt>&);

    // TEMPLATE swap FUNCTIONS
template <class Elem, class RXtraits>
  void swap(basic_regex <Elem, RXtraits>& left,
    basic_regex <Elem, RXtraits>& right) throw ();
template <class Elem, class IOtraits,
  class BidIt, class Alloc>
  void swap(match_results <BidIt, Alloc>& left,
    match_results <BidIt, Alloc>& right) throw ();

    // COMPARISON OPERATORS FOR match_results
template <class BidIt , class Alloc>
  bool operator ==( const match_results <BidIt, Alloc>&,
    const match_results <BidIt, Alloc>&);
template <class BidIt , class Alloc>
  bool operator !=( const match_results <BidIt, Alloc>&,
    const match_results <BidIt , Alloc>&);

    // COMPARISON OPERATORS FOR sub_match
template <class BidIt>
  bool operator ==( const sub_match <BidIt >&,
    const sub_match <BidIt>&);
template <class BidIt>
  bool operator !=( const sub_match <BidIt >&,
    const sub_match <BidIt>&);
template <class BidIt >
  bool operator <( const sub_match <BidIt >&,
    const sub_match <BidIt>&);
template <class BidIt>
  bool operator <=( const sub_match <BidIt >&,
    const sub_match <BidIt>&);
template <class BidIt>
  bool operator>( const sub_match <BidIt >&,
    const sub_match <BidIt >&);
template <class BidIt >
  bool operator>=( const sub_match <BidIt >&,
    const sub_match <BidIt >&);

template <class BidIt, class IOtraits, class Alloc>
  bool operator ==(
    const basic_string <
      typename iterator_traits <BidIt >:: value_type,
      IOtraits, Alloc>&,
    const sub_match <BidIt >&);
template <class BidIt, class IOtraits, class Alloc>
  bool operator !=(
    const basic_string <
      typename iterator_traits <BidIt >:: value_type,
      IOtraits, Alloc>&,
    const sub_match <BidIt >&);
template <class BidIt, class IOtraits, class Alloc>
  bool operator <(
    const basic_string <
      typename iterator_traits <BidIt >:: value_type,
      IOtraits, Alloc>&,
    const sub_match <BidIt >&);
template <class BidIt, class IOtraits, class Alloc>
  bool operator <=(
    const basic_string <
      typename iterator_traits <BidIt >:: value_type,
      IOtraits, Alloc>&,
    const sub_match <BidIt >&);
template <class BidIt, class IOtraits, class Alloc>
  bool operator>(
    const basic_string <
      typename iterator_traits <BidIt >:: value_type,
      IOtraits, Alloc>&,
    const sub_match <BidIt >&);
template <class BidIt, class IOtraits, class Alloc>
  bool operator>=(
  const basic_string <
    typename iterator_traits <BidIt >:: value_type,
    IOtraits, Alloc>&,
  const sub_match <BidIt >&);

template <class BidIt, class IOtraits, class Alloc>
  bool operator ==( const sub_match <BidIt >&,
    const basic_string <
      typename iterator_traits <BidIt >:: value_type,
      IOtraits, Alloc>&);
template <class BidIt, class IOtraits, class Alloc>
  bool operator !=( const sub_match <BidIt >&,
    const basic_string <
      typename iterator_traits <BidIt >:: value_type,
      IOtraits, Alloc>&);
template <class BidIt, class IOtraits, class Alloc>
  bool operator <( const sub_match <BidIt >&,
    const basic_string <
      typename iterator_traits <BidIt >:: value_type,
      IOtraits, Alloc>&);
template <class BidIt, class IOtraits, class Alloc>
  bool operator <=( const sub_match <BidIt >&,
    const basic_string <
      typename iterator_traits <BidIt >:: value_type,
      IOtraits, Alloc>&);
template <class BidIt, class IOtraits, class Alloc>
  bool operator>( const sub_match <BidIt >&,
    const basic_string <
      typename iterator_traits <BidIt >:: value_type,
      IOtraits, Alloc>&);
template <class BidIt, class IOtraits, class Alloc>
  bool operator>=( const sub_match <BidIt >&,
    const basic_string <
      typename iterator_traits <BidIt >:: value_type,
      IOtraits, Alloc>&);

template <class BidIt >
  bool operator ==(
    const typename iterator_traits <BidIt >:: value_type*,
    const sub_match <BidIt >&);
template <class BidIt >
  bool operator !=(
    const typename iterator_traits <BidIt >:: value_type*,
    const sub_match <BidIt >&);
template <class BidIt >
  bool operator <(
    const typename iterator_traits <BidIt >:: value_type*,
    const sub_match <BidIt >&);
template <class BidIt >
  bool operator <=(
    const typename iterator_traits <BidIt >:: value_type*,
    const sub_match <BidIt >&);
template <class BidIt >
  bool operator>(
    const typename iterator_traits <BidIt >:: value_type*,
    const sub_match <BidIt >&);
template <class BidIt >
  bool operator>=(
    const typename iterator_traits <BidIt >:: value_type*,
    const sub_match <BidIt >&);

template <class BidIt >
  bool operator ==( const sub_match <BidIt >&,
    const typename iterator_traits <BidIt >:: value_type *);
template <class BidIt >
  bool operator !=( const sub_match <BidIt >&,
    const typename iterator_traits <BidIt >:: value_type *);
template <class BidIt>
  bool operator <( const sub_match <BidIt >&,
    const typename iterator_traits <BidIt >:: value_type *);
template <class BidIt>
  bool operator <=( const sub_match <BidIt >&,
    const typename iterator_traits <BidIt >:: value_type *);
template <class BidIt>
  bool operator>( const sub_match <BidIt >&,
    const typename iterator_traits <BidIt >:: value_type *);
template <class BidIt>
  bool operator>=( const sub_match <BidIt >&,
    const typename iterator_traits <BidIt >:: value_type *);

template <class BidIt>
  bool operator ==(
    const typename iterator_traits <BidIt >:: value_type&,
    const sub_match <BidIt >&);
template <class BidIt>
  bool operator !=(
    const typename iterator_traits <BidIt >:: value_type&,
    const sub_match <BidIt >&);
template <class BidIt>
  bool operator <(
    const typename iterator_traits <BidIt >:: value_type&,
    const sub_match <BidIt >&);
template <class BidIt>
  bool operator <=(
    const typename iterator_traits <BidIt >:: value_type&,
    const sub_match <BidIt >&);
template <class BidIt>
  bool operator>(
    const typename iterator_traits <BidIt >:: value_type&,
    const sub_match <BidIt >&);
template <class BidIt>
  bool operator>=(
    const typename iterator_traits <BidIt >:: value_type&,
    const sub_match <BidIt >&);

template <class BidIt>
  bool operator ==( const sub_match <BidIt >&,
    const typename iterator_traits <BidIt >:: value_type &);
template <class BidIt>
  bool operator !=( const sub_match <BidIt >&,
    const typename iterator_traits <BidIt >:: value_type &);
template <class BidIt>
  bool operator <( const sub_match <BidIt >&,
    const typename iterator_traits <BidIt >:: value_type &);
template <class BidIt>
  bool operator <=( const sub_match <BidIt >&,
    const typename iterator_traits <BidIt >:: value_type &);
template <class BidIt>
  bool operator>( const sub_match <BidIt >&,
    const typename iterator_traits <BidIt >:: value_type &);
template <class BidIt>
  bool operator>=( const sub_match <BidIt >&,
    const typename iterator_traits <BidIt >:: value_type &);
} }


Section A.2. Header <unordered_set> Synopsis

A.2. Header <unordered_set> Synopsis

namespace std {     // C++ standard library
 namespace tr1 {    // TR1 additions

    // CLASS TEMPLATE unordered_set
template < class Key,
  class Hash = hash <Key>,
  class Pred = equal_to <Key >,
  class Alloc = allocator <Key >>
    class unordered_set ;

    // CLASS TEMPLATE unordered_multiset
template <class Key,
  class Hash = hash <Key >,
  class Pred = equal_to <Key >,
  class Alloc = allocator <Key >>
    class unordered_multiset ;

    // FUNCTION TEMPLATES swap
template <class Key, class Hash, class Pred, class Alloc>
void swap (unordered_set (Key, Hash, Pred, Alloc>& left,
    unordered_set (Key, Hash, Pred, Alloc>& right);
template <class Key, class Hash, class Pred, class Alloc>
void swap ( unordered_multiset (Key, Hash, Pred, Alloc>& left,
  unordered_multiset (Key, Hash, Pred, Alloc>& right);

    // CLASS TEMPLATE unordered_set
template <class Key,
  class Hash = hash <Key >,
  class Pred = equal_to <Key >,
  class Alloc = allocator <Key >>
  class unordered_set {
public :

    // NESTED TYPES
  typedef Key key_type ;
  typedef Hash hasher ;
  typedef Pred key_equal ;
  typedef Key value_type ;

  typedef Alloc allocator_type ;
  typedef Alloc :: pointer pointer ;
  typedef Alloc :: const_pointer const_pointer ;
  typedef Alloc :: reference reference ;
  typedef Alloc :: const_reference const_reference ;

  typedef T0 iterator ;
  typedef T1 const_iterator ;
  typedef T2 local_iterator ;
  typedef T3 const_local_iterator ;
  typedef T4 size_type ;
  typedef T5 difference_type ;

    // CONSTRUCTING AND ASSIGNING
  explicit unordered_set (
    size_type n = n0 , // implementation-defined
    const hasher & h = hasher (),
    const key_equal & comp = key_equal (),
    const allocator_type & alloc = allocator_type ());
  template <class InIt>
    unordered_set (InIt first, InIt last,
    size_type n = n0 , // implementation-defined
    const hasher & h = hasher (),
    const key_equal & comp = key_equal (),
    const allocator_type & alloc = allocator_type ());
  unordered_set (const unordered_set & right);
  unordered_set & operator= (const unordered_set & right );

    // MODIFYING
  pair <iterator, bool> insert (const value_type & val);
  iterator insert (
    iterator where, const value_type & val);
  const_iterator insert (
    const_iterator where, const value_type& val);
  template <class InIt>
    void insert (InIt first, InIt last);

  iterator erase (iterator where);
  const_iterator erase ( const_iterator where);
  size_type erase (const Key & key);
  iterator erase (
    iterator first, iterator last);
  const_iterator erase (
    const_iterator first, const_iterator last);
  void clear ();

  void swap (unordered_set & right);

    // ITERATING
  iterator begin ();
  iterator end ();
  const_iterator begin () const;
  const_iterator end () const ;

    // SEARCHING
  iterator find (const Key & key);
  const_iterator find (const Key & key) const;
  size_type count (const Key & key) const;
  pair <iterator, iterator>
    equal_range (const Key & key);
  pair <const_iterator, const_iterator>
    equal_range (const Key & key) const;

    // QUERYING
  size_type size () const ;
  size_type max_size () const;
  bool empty () const;

  allocator_type get_allocator () const;
  hasher hash_function () const ;
  key_equal key_eq () const ;

    // TUNING
  local_iterator begin (size_type n);
  const_local_iterator begin (size_type n) const;
  local_iterator end (size_type n);
  const_local_iterator end (size_type n) const ;

  size_type bucket_count () const ;
  size_type max_bucket_count () const ;
  size_type bucket_size (size_type n) const;
  size_type bucket (const key_type & val) const ;

  float load_factor () const ;
  float max_load_factor () const;
  void max_load_factor (float fact);
  void rehash (size_type n);
  };

    // CLASS TEMPLATE unordered_multiset
template <class Key,
  class Ty,
  class Hash = hash <Key >,
  class Pred = equal_to <Key >,
  class Alloc = allocator <Key >
  class unordered_multiset {
    // CONTENTS ARE THE SAME AS unordered_set
  };

} }


Section A.3. Header <unordered_map> Synopsis

A.3. Header <unordered_map> Synopsis

namespace std {    // C++ standard library
 namespace tr1 {   // TR1 additions

    // CLASS TEMPLATE unordered_map
template <class Key, class Ty,
  class Hash = hash <Key>,
  class Pred = equal_to <Key>,
  class Alloc = allocator <pair <const Key, Ty>>>
    class unordered_map ;

    // CLASS TEMPLATE unordered_multimap
template <class Key, class Ty,
  class Hash = hash <Key>,
  class Pred = equal_to <Key>,
  class Alloc = allocator <pair <const Key, Ty>>>
  class unordered_multimap ;

    // FUNCTION TEMPLATES swap
template <class Key, class Ty, class Hash,
  class Pred, class Alloc>
void swap (unordered_map (Key, Ty, Hash, Pred, Alloc>& left,
  unordered_map (Key, Ty, Hash, Pred, Alloc>& right);
template <class Key, class Ty, class Hash, class Pred,
  class Alloc>
void swap (
  unordered_multimap (Key, Ty, Hash, Pred, Alloc>& left,
  unordered_multimap (Key, Ty, Hash, Pred, Alloc>& right);

    // CLASS TEMPLATE unordered_map
template <class Key,
  class Ty,
  class Hash = hash <Key>,
  class Pred = equal_to <Key>,
  class Alloc = allocator <pair <const Key, Ty>>>
  class unordered_map {
public :

    // NESTED TYPES
  typedef Key key_type ;
  typedef Hash hasher ;
  typedef Pred key_equal ;
  typedef pair <const Key, Ty> value_type ;
  typedef Ty mapped_type ;
  typedef Alloc allocator_type ;
  typedef Alloc :: pointer pointer ;
  typedef Alloc :: const_pointer const_pointer ;
  typedef Alloc :: reference reference ;
  typedef Alloc :: const_reference const_reference ;

  typedef T0 iterator ;
  typedef T1 const_iterator ;
  typedef T2 local_iterator ;
  typedef T3 const_local_iterator ;
  typedef T4 size_type ;
  typedef T5 difference_type ;

    // CONSTRUCTING AND ASSIGNING
explicit unordered_map (
  size_type n = n0, // implementation-defined
  const hasher & h = hasher (),
  const key_equal & comp = key_equal (),
  const allocator_type & alloc = allocator_type ());
template <class InIt>
  unordered_map (InIt first, InIt last,
  size_type n = n0, // implementation-defined
  const hasher & h = hasher (),
  const key_equal & comp = key_equal (),
  const allocator_type & alloc = allocator_type ());
unordered_map (const unordered_map & right);
unordered_map & operator= (const unordered_map & right);

    // MODIFYING
  pair <iterator, bool> insert (const value_type & val);
  iterator insert (
    iterator where, const value_type & val);
  const_iterator insert (
    const_iterator where, const value_type& val);
  template <class InIt>
    void insert (InIt first, InIt last);

  iterator erase (iterator where);
  const_iterator erase ( const_iterator where);
  size_type erase (const Key & keyval);
  iterator erase (
    iterator first, iterator last);
  const_iterator erase (
    const_iterator first, const_iterator last);
  void clear ();

  void swap (unordered_map & right);

    // ITERATING
  iterator begin ();
  iterator end ();
  const_iterator begin () const;
  const_iterator end () const ;

    // SEARCHING
  iterator find (const Key & keyval);
  const_iterator find (const Key & keyval) const;
  size_type count (const Key & keyval) const;
  pair <iterator, iterator>
    equal_range (const Key & keyval);
  pair <const_iterator, const_iterator>
    equal_range (const Key & keyval) const;
  mapped_type & operator []( const Key & keyval);
  const mapped_type & operator []( const Key & keyval) const;

    // QUERYING
  size_type size () const ;
  size_type max_size () const;
  bool empty () const;

  allocator_type get_allocator () const;
  hasher hash_function () const ;
  key_equal key_eq () const ;

    // TUNING
  local_iterator begin (size_type n);
  const_local_iterator begin (size_type n) const;
  local_iterator end (size_type n);
  const_local_iterator end (size_type n) const ;

  size_type bucket_count () const;
  size_type max_bucket_count () const ;
  size_type bucket_size (size_type n) const;
  size_type bucket (const key_type & val) const ;

  float load_factor () const ;
  float max_load_factor () const ;
  void max_load_factor (float fact);
  void rehash (size_type n);
  };

    // CLASS TEMPLATE unordered_multimap
template <class Key,
  class Ty,
  class Hash = hash <Key>,
  class Pred = equal_to <Key>,
  class Alloc = allocator <pair <const Key, Ty>>>
  class unordered_multimap {
    // CONTENTS ARE THE SAME AS unordered_map WITHOUT operator[]
  };

} }


Section A.4. Header <float.h> Synopsis

A.4. Header <float.h> Synopsis

# define FLT_RADIX <# if expression >= 2 >
# define FLT_ROUNDS < integer rvalue >
# define FLT_EVAL_METHOD <# if expression >
# define DECIMAL_DIG <# if expression >= 10 >

# define DBL_DIG <# if expression >= 10 >
# define DBL_EPSILON < double constant <= 10-9 >
# define DBL_MANT_DIG <# if expression >
# define DBL_MAX < double constant >= 1037 >
# define DBL_MAX_10_EXP <# if expression >= 37 >
# define DBL_MAX_EXP <# if expression >
# define DBL_MIN < double constant <= 10-37 >
# define DBL_MIN_10_EXP <# if expression <= -37 >
# define DBL_MIN_EXP <# if expression >

# define FLT_DIG <# if expression >= 6 >
# define FLT_EPSILON < float constant <= 10-5 >
# define FLT_MANT_DIG <# if expression >
# define FLT_MAX < float constant >= 1037 >
# define FLT_MAX_10_EXP <# if expression >= 37 >
# define FLT_MAX_EXP <# if expression >
# define FLT_MIN < float constant <= 10-37 >
# define FLT_MIN_10_EXP <# if expression <= -37 >
# define FLT_MIN_EXP <# if expression >

# define LDBL_DIG <# if expression >= 10 >
# define LDBL_EPSILON < long double constant <= 10-9 >
# define LDBL_MANT_DIG <# if expression >
# define LDBL_MAX < long double constant >= 1037 >
# define LDBL_MAX_10_EXP <# if expression >= 37 >
# define LDBL_MAX_EXP <# if expression >
# define LDBL_MIN < long double constant <= 10-37 >
# define LDBL_MIN_10_EXP <# if expression <= -37 >
# define LDBL_MIN_EXP <# if expression >


Section A.5. Header <math.h> Synopsis

A.5. Header <math.h> Synopsis

    // MACROS
#define HUGE_VAL <double rvalue>
#define HUGE_VALF <float rvalue>
#define HUGE_VALL <long double rvalue>

#define INFINITY <float rvalue>
#define NAN <float rvalue>

#define FP_FAST_FMA <integer constant expression>
#define FP_FAST_FMAF <integer constant expression>
#define FP_FAST_FMAL <integer constant expression>

#define FP_INFINITE <integer constant expression>
#define FP_NAN <integer constant expression>
#define FP_NORMAL <integer constant expression>
#define FP_SUBNORMAL <integer constant expression>
#define FP_ZERO <integer constant expression>

#define FP_ILOGB0 <integer constant expression>
#define FP_ILOGBNAN <integer constant expression>

#define MATH_ERRNO       1
#define MATH_ERREXCEPT    2
#define math_errhandling <int rvalue // [0,4)>

    // TYPES
typedef f-type double_t ;
typedef f-type float_t ;

    // GENERIC FUNCTION MACROS macros in C, functions in C++
#define signbit (x) <int rvalue>

#define fpclassify (x) <int rvalue>
#define isfinite (x) <int rvalue>
#define isinf (x) <int rvalue>
#define isnan (x) <int rvalue>
#define isnormal (x) <int rvalue>

#define isgreater (x, y) <int rvalue>
#define isgreaterequal (x, y) <int rvalue>
#define isless (x, y) <int rvalue>
#define islessequal (x, y) <int rvalue>
#define islessgreater (x, y) <int rvalue>
#define isunordered (x, y) <int rvalue>

    // FUNCTIONS
double abs (double x); // C++ only
float abs (float x); // C++ only
long double abs (long double x); // C++ only

double acos (double x);
float acos (float x); // C++ only
long double acos (long double x); // C++ only
float acosf (float x); // required with C99
long double acosl (long double x); // required with C99

double asin (double x);
float asin (float x); // C++ only
long double asin (long double x); // C++ only
float asinf (float x); // required with C99
long double asinl (long double x); // required with C99

double atan (double x);
float atan (float x); // C++ only
long double atan (long double x); // C++ only
float atanf (float x); // required with C99
long double atanl (long double x); // required with C99

double atan2 (double y, double x);
float atan2 (float y, float x); // C++ only
long double atan2 (long double y, long double x); // C++ only
float atan2f (float y, float x); // required with C99
long double atan2l (long double y,
    long double x); // required with C99

double ceil (double x);
float ceil (float x); // C++ only
long double ceil (long double x); // C++ only
float ceilf (float x); // required with C99
long double ceill (long double x); // required with C99

double cos (double x);
float cos (float x); // C++ only
long double cos (long double x); // C++ only
float cosf (float x); // required with C99
long double cosl (long double x); // required with C99

double cosh (double x);
float cosh (float x); // C++ only
long double cosh (long double x); // C++ only
float coshf (float x); // required with C99
long double coshl (long double x); // required with C99

double exp (double x);
float exp (float x); // C++ only
long double exp (long double x); // C++ only
float expf (float x); // required with C99
long double expl (long double x); // required with C99

double fabs (double x);
float fabs (float x); // C++ only
long double fabs (long double x); // C++ only
float fabsf (float x); // required with C99
long double fabsl (long double x); // required with C99

double floor (double x);
float floor (float x); // C++ only
long double floor (long double x); // C++ only
float floorf (float x); // required with C99
long double floorl (long double x); // required with C99

double fmod (double x, double y);
float fmod (float x, float y); // C++ only
long double fmod (long double x, long double y); // C++ only
float fmodf (float x, float y); // required with C99
long double fmodl (long double x,
    long double y); // required with C99

double frexp (double x, int * pexp);
float frexp (float x, int *pexp); // C++ only
long double frexp (long double x, int *pexp); // C++ only
float frexpf (float x, int * pexp); // required with C99
long double frexpl (long double x, int *pexp);// required with C99

double ldexp (double x, int ex);
float ldexp (float x, int ex); // C++ only
long double ldexp (long double x, int ex); // C++ only
float ldexpf (float x, int ex); // required with C99
long double ldexpl (long double x, int ex); // required with C99

double log (double x);
float log (float x); // C++ only
long double log (long double x); // C++ only
float logf (float x); // required with C99
long double logl (long double x); // required with C99

double log10 (double x);
float log10 (float x); // C++ only
long double log10 (long double x); // C++ only
float log10f (float x); // required with C99
long double log10l (long double x); // required with C99

double modf (double x, double *pint);
float modf (float x, float *pint); // C++ only
long double modf (long double x,
    long double * pint); // C++ only
float modff (float x, float * pint); // required with C99
long double modfl (long double x,
    long double * pint); // required with C99

double pow (double x, double y);
float pow (float x, float y); // C++ only
long double pow (long double x, long double y); // C++ only
double pow (double x, int y); // C++ only
float pow (float x, int y); // C++ only
long double pow (long double x, int y); // C++ only
float powf (float x, float y); // required with C99
long double powl (long double x,
    long double y); // required with C99

double sin (double x);
float sin (float x); // C++ only
long double sin (long double x); // C++ only
float sinf (float x); // required with C99
long double sinl (long double x); // required with C99

double sinh (double x);
float sinh (float x); // C++ only
long double sinh (long double x); // C++ only
float sinhf (float x); // required with C99
long double sinhl (long double x); // required with C99

double sqrt (double x);
float sqrt (float x); // C++ only
long double sqrt (long double x); // C++ only
float sqrtf (float x); // required with C99
long double sqrtl (long double x); // required with C99

double tan (double x);
float tan (float x); // C++ only
long double tan (long double x); // C++ only
float tanf (float x); // required with C99
long double tanl (long double x); // required with C99

double tanh (double x);
float tanh (float x); // C++ only
long double tanh (long double x); // C++ only
float tanhf (float x); // required with C99
long double tanhl (long double x); // required with C99

double acosh (double x);
float acosh (float x); // C++ only
long double acosh (long double x); // C++ only
float acoshf (float x);
long double acoshl (long double x);

double asinh (double x);
float asinh (float x); // C++ only
long double asinh (long double x); // C++ only
float asinhf (float x);
long double asinhl (long double x);

double atanh (double x);
float atanh (float x); // C++ only
long double atanh (long double x); // C++ only
float atanhf (float x);
long double atanhl (long double x);

double cbrt (double x);
float cbrt (float x); // C++ only
long double cbrt (long double x); // C++ only
float cbrtf (float x);
long double cbrtl (long double x);

double copysign (double x, double y);
float copysign (float x, float y); // C++ only
long double copysign (long double x,
  long double y); // C++ only
float copysignf (float x, float y);
long double copysignl (long double x, long double y);

double erf (double x);
float erf (float x); // C++ only
long double erf (long double x); // C++ only
float erff (float x);
long double erfl (long double x);

double erfc (double x);
float erfc (float x); // C++ only
long double erfc (long double x); // C++ only
float erfcf (float x);
long double erfcl (long double x);

double exp2 (double x);
float exp2 (float x); // C++ only
long double exp2 (long double x); // C++ only
float exp2f (float x);
long double exp2l (long double x);

double expm1 (double x);
float expm1 (float x); // C++ only
long double expm1 (long double x); // C++ only
float expm1f (float x);
long double expm1l (long double x);

double fdim (double x, double y);
float fdim (float x, float y); // C++ only
long double fdim (long double x, long double y); // C++ only
float fdimf (float x, float y);
long double fdiml (long double x, long double y);

double fma (double x, double y, double z);
float fma (float x, float y, float z); // C++ only
long double fma (long double x, long double y,
  long double z); // C++ only
float fmaf (float x, float y, float z);
long double fmal (long double x, long double y,
  long double z);

double fmax (double x, double y);
float fmax (float x, float y); // C++ only
long double fmax (long double x, long double y); // C++ only
float fmaxf (float x, float y);
long double fmaxl (long double x, long double y);

double fmin (double x, double y);
float fmin (float x, float y); // C++ only
long double fmin (long double x, long double y); // C++ only
float fminf (float x, float y);
long double fminl (long double x, long double y);

double hypot (double x, double y);
float hypot (float x, float y); // C++ only
long double hypot (long double x, long double y); // C++ only
float hypotf (float x, float y);
long double hypotl (long double x, long double y);

int ilogb (double x);
int ilogb (float x); // C++ only
int ilogb (long double x); // C++ only
int ilogbf (float x);
int ilogbl (long double x);

double lgamma (double x);
float lgamma (float x); // C++ only
long double lgamma (long double x); // C++ only
float lgammaf (float x);
long double lgammal (long double x);

long long llrint (double x);
long long llrint (float x); // C++ only
long long llrint (long double x); // C++ only
long long llrintf (float x);
long long llrintl (long double x);

long long llround (double x);
long long llround (float x); // C++ only
long long llround (long double x); // C++ only
long long llroundf (float x);
long long llroundl (long double x);

double log1p (double x);
float log1p (float x); // C++ only
long double log1p (long double x); // C++ only
float log1pf (float x);
long double log1pl (long double x);

double log2 (double x);
float log2 (float x); // C++ only
long double log2 (long double x); // C++ only
float log2f (float x);
long double log2l (long double x);

double logb (double x);
float logb (float x); // C++ only
long double logb (long double x); // C++ only
float logbf (float x);
long double logbl (long double x);

long lrint (double x);
long lrint (float x); // C++ only
long lrint (long double x); // C++ only
long lrintf (float x);
long lrintl (long double x);

long lround (double x);
long lround (float x); // C++ only
long lround (long double x); // C++ only
long lroundf (float x);
long lroundl (long double x);

double nan (const char *str);
float nanf (const char *str);
long double nanl (const char *str);

double nearbyint (double x);
float nearbyint (float x); // C++ only
long double nearbyint (long double x); // C++ only
float nearbyintf (float x);
long double nearbyintl (long double x);

double nextafter (double x, double y);
float nextafter (float x, float y); // C++ only
long double nextafter (long double x,
  long double y); // C++ only
float nextafterf (float x, float y);
long double nextafterl (long double x, long double y);

double nexttoward (double x, long double y);
float nexttoward (float x, long double y); // C++ only
long double nexttoward (long double x,
  long double y); // C++ only
float nexttowardf (float x, long double y);
long double nexttowardl (long double x, long double y);

double remainder (double x, double y);
float remainder (float x, float y); // C++ only
long double remainder (long double x,
  long double y); // C++ only
float remainderf (float x, float y);
long double remainderl (long double x, long double y);

double remquo (double x, double y, int *pquo);
float remquo (float x, float y, int *pquo); // C++ only
long double remquo (long double x, long double y,
  int *pquo); // C++ only
float remquof (float x, float y, int * pquo);
long double remquol (long double x, long double y,
  int *pquo);

double rint (double x);
float rint (float x); // C++ only
long double rint (long double x); // C++ only
float rintf (float x);
long double rintl (long double x);

double round (double x);
float round (float x); // C++ only
long double round (long double x); // C++ only
float roundf (float x);
long double roundl (long double x);

double scalbln (double x, long ex);
float scalbln (float x, long ex); // C++ only
long double scalbln (long double x, long ex); // C++ only
float scalblnf (float x, long ex);
long double scalblnl (long double x, long ex);

double scalbn (double x, int ex);
float scalbn (float x, int ex); // C++ only
long double scalbn (long double x, int ex); // C++ only
float scalbnf (float x, int ex);
long double scalbnl (long double x, int ex);

double tgamma (double x);
float tgamma (float x); // C++ only
long double tgamma (long double x); // C++ only
float tgammaf (float x);
long double tgammal (long double x);

double trunc (double x);
float trunc (float x); // C++ only
long double trunc (long double x); // C++ only
float truncf (float x);
long double truncl (long double x);

double laguerre (unsigned n, double x);
float laguerre (unsigned n, float x); // C++ only
long double laguerre (unsigned n, long double x); // C++ only
float laguerref (unsigned n, float x);
long double laguerrel (unsigned n, long double x);

double assoc_laguerre (unsigned n, unsigned m,
  double x);
float assoc_laguerre (unsigned n, unsigned m,
  float x); // C++ only
long double assoc_laguerre (unsigned n, unsigned m,
  long double x); // C++ only
float assoc_laguerref (unsigned n, unsigned m,
  float x);
long double assoc_laguerrel (unsigned n, unsigned m,
  long double x);

double legendre (unsigned l, double x);
float legendre (unsigned l, float x); // C++ only
long double legendre (unsigned l, long double x); // C++ only
float legendref (unsigned l, float x);
long double legendrel (unsigned l, long double x);

double assoc_legendre (unsigned l, unsigned m,
  double x);
float assoc_legendre (unsigned l, unsigned m,
  float x); // C++ only
long double assoc_legendre (unsigned l, unsigned m,
  long double x); // C++ only
float assoc_legendref (unsigned l, unsigned m,
  float x);
long double assoc_legendrel (unsigned l, unsigned m,
  long double x);

double sph_legendre (unsigned l, unsigned m,
  double theta);
float sph_legendre (unsigned l, unsigned m,
  float theta); // C++ only
long double sph_legendre (unsigned l, unsigned m,
  long double theta); // C++ only
float sph_legendref (unsigned l, unsigned m,
  float theta);
long double sph_legendrel (unsigned l, unsigned m,
  long double theta);

double beta (double x, double y);
float beta (float x, float y); // C++ only
long double beta (long double x, long double y); // C++ only
float betaf (float x, float y);
long double betal (long double x, long double y);

double ellint_1 (double k, double phi);
float ellint_1 (float k, float phi); // C++ only
long double ellint_1 (long double k,
  long double phi); // C++ only
float ellint_1f (float k, float phi);
long double ellint_1l (long double k, long double phi);

double ellint_2 (double k, double phi);
float ellint_2 (float k, float phi); // C++ only
long double ellint_2 (long double k,
  long double phi); // C++ only
float ellint_2f (float k, float phi);
long double ellint_2l (long double k, long double phi);

double ellint_3 (double k, double nu,
  double phi);
float ellint_3 (float k, float nu,
  float phi); // C++ only
long double ellint_3 (long double k, long double nu,
  long double phi); // C++ only
float ellint_3f (float k, float nu,
  float phi);
long double ellint_3l (long double k, long double nu,
  long double phi);

double comp_ellint_1 (double k);
float comp_ellint_1 (float k); // C++ only
long double comp_ellint_1 (long double k); // C++ only
float comp_ellint_1f (float k);
long double comp_ellint_1l (long double k);

double comp_ellint_2 (double k);
float comp_ellint_2 (float k); // C++ only
long double comp_ellint_2 (long double k); // C++ only
float comp_ellint_2f (float k);
long double comp_ellint_2l (long double k);

double comp_ellint_3 (double k, double nu);
float comp_ellint_3 (float k, float nu); // C++ only
long double comp_ellint_3 (long double k,
  long double nu); // C++ only
float comp_ellint_3f (float k, float nu);
long double comp_ellint_3l (long double k, long double nu);

double cyl_bessel_i (double nu, double x);
float cyl_bessel_i (float nu, float x); // C++ only
long double cyl_bessel_i (long double nu,
  long double x); // C++ only
float cyl_bessel_if (float nu, float x);
long double cyl_bessel_il (long double nu, long double x);

double cyl_bessel_j (double nu, double x);
float cyl_bessel_j (float nu, float x); // C++ only
long double cyl_bessel_j (long double nu,
  long double x); // C++ only
float cyl_bessel_jf (float nu, float x);
long double cyl_bessel_jl (long double nu, long double x);

double cyl_bessel_k (double nu, double x);
float cyl_bessel_k (float nu, float x); // C++ only
long double cyl_bessel_k (long double nu,
  long double x); // C++ only
float cyl_bessel_kf (float nu, float x);
long double cyl_bessel_kl (long double nu, long double x);

double sph_bessel (unsigned n, double x);
float sph_bessel (unsigned n, float x); // C++ only
long double sph_bessel (unsigned n, long double x); // C++ only
float sph_besself (unsigned n, float x);
long double sph_bessell (unsigned n, long double x);

double cyl_neumann (double nu, double x);
float cyl_neumann (float nu, float x); // C++ only
long double cyl_neumann (long double nu,
  long double x); // C++ only
float cyl_neumannf (float nu, float x);
long double cyl_neumannl (long double nu, long double x);

double sph_neumann (unsigned n, double x);
float sph_neumann (unsigned n, float x); // C++ only
long double sph_neumann (unsigned n,
  long double x); // C++ only
float sph_neumannf (unsigned n, float x);
long double sph_neumannl (unsigned n, long double x);

double expint (double x);
float expint (float x); // C++ only
long double expint (long double x); // C++ only
float expintf (float x);
long double expintl (long double x);

double hermite (unsigned n, double x);
float hermite (unsigned n, float x); // C++ only
long double hermite (unsigned n, long double x); // C++ only
float hermitef (unsigned n, float x);
long double hermitel (unsigned n, long double x);

double riemann_zeta (double x);
float riemann_zeta (float x); // C++ only
long double riemann_zeta (long double x); // C++ only
float riemann_zetaf (float x);
long double riemann_zetal (long double x);


Section A.6. Header <functional> Synopsis

A.6. Header <functional> Synopsis

namespace std {
template <class Arg, class Result>
  struct unary_function ;
template <class Arg1, class Arg2, class Result>
  struct binary_function ;
template <class Ty>
  struct plus ;
template <class Ty>
  struct minus ;
template <class Ty>
  struct multiplies ;
template <class Ty>
  struct divides ;
template <class Ty>
  struct modulus ;
template <class Ty>
  struct negate ;
template <class Ty>
  struct equal_to ;
template <class Ty>
  struct not_equal_to ;
template <class Ty>
  struct greater ;
template <class Ty>
  struct less ;
template <class Ty>
  struct greater_equal ;
template <class Ty>
  struct less_equal ;
template <class Ty>
  struct logical_and ;
template <class Ty>
  struct logical_or ;
template <class Ty>
  struct logical_not ;
template <class Fn1>
  struct unary_negate ;
template <class Fn2>
  struct binary_negate ;
template <class Fn2>
  class binder1st ;
template <class Fn2>
  class binder2nd ;
template <class Arg, class Result>
  class pointer_to_unary_function ;
template <class Arg1, class Arg2, class Result>
  class pointer_to_binary_function ;
template <class Result, class Ty>
  struct mem_fun_t ;
template <class Result, class Ty, class Arg>
  struct mem_fun1_t ;
template <class Result, class Ty>
  struct const_mem_fun_t ;
template <class Result, class Ty, class Arg>
  struct const_mem_fun1_t ;
template <class Result, class Ty>
  struct mem_fun_ref_t ;
template <class Result, class Ty, class Arg>
  struct mem_fun1_ref_t ;
template <class Result, class Ty>
  struct const_mem_fun_ref_t ;
template <class Result, class Ty, class Arg>
  struct const_mem_fun1_ref_t ;

    // TEMPLATE FUNCTIONS
template <class Fn1>
  unary_negate <Fn1> not1 (const Fn1 & func);
template <class Fn2>
  binary_negate <Fn2> not2 (const Fn2 & func);
template <class Fn2, class Ty>
  binder1st <Fn2> bind1st (const Fn2 & func, const Ty& left);
template <class Fn2, class Ty>
  binder2nd <Fn2> bind2nd (
    const Fn2 & func, const Ty& right);
template <class Arg, class Result>
  pointer_to_unary_function <Arg, Result>
    ptr_fun (Result (*)( Arg));
template <class Arg1, class Arg2, class Result>
  pointer_to_binary_function <Arg1, Arg2, Result>
    ptr_fun (Result (*)( Arg1, Arg2));
template <class Result, class Ty>
  mem_fun_t <Result, Ty> mem_fun (Result (Ty::* pm)());
template <class Result, class Ty, class Arg>
  mem_fun1_t <Result, Ty, Arg> mem_fun (
    Result (Ty::* pm)(Arg left));
template <class Result, class Ty>
  const_mem_fun_t <Result, Ty> mem_fun (
    Result (Ty::* pm)() const);
template <class Result, class Ty, class Arg>
  const_mem_fun1_t <Result, Ty, Arg> mem_fun (
    Result (Ty::* pm)(Arg left) const);
template <class Result, class Ty>
  mem_fun_ref_t <Result, Ty> mem_fun_ref (
    Result (Ty::* pm)());
template <class Result, class Ty, class Arg>
  mem_fun1_ref_t <Result, Ty, Arg>
    mem_fun_ref (Result (Ty::* pm)(Arg left));
template <class Result, class Ty>
  const_mem_fun_ref_t <Result, Ty> mem_fun_ref (
    Result (Ty::* pm)() const);
template <class Result, class Ty, class Arg>
  const_mem_fun1_ref_t <Result, Ty, Arg>
    mem_fun_ref (Result (Ty::* pm)(Arg left) const);

  namespace tr1 {
    // REFERENCE WRAPPERS
template <class Ty> reference_wrapper <Ty>
  ref (Ty&);
template <class Ty> reference_wrapper <Ty>
  ref (reference_wrapper <Ty>&);
template <class Ty> reference_wrapper <const Ty>
  cref (const Ty&);
template <class Ty> reference_wrapper <const Ty>
  cref (const reference_wrapper <Ty>&);
template <class Ty>
  struct reference_wrapper ;

    // FUNCTION OBJECT RETURN TYPES
template <class Ty>
  struct result_of ;

    // ENHANCED MEMBER POINTER ADAPTER
template <class Ret, class Ty>
  unspecified mem_fn (Ret Ty ::*);

    // FUNCTION OBJECT WRAPPERS
class bad_function_call ;
template <class Fty>
  class function ;
template <class Fty>
  void swap (function <Fty>& f1,
    function <Fty>& f2);
template <class Fty>
  bool operator!= (const function <Fty>&,
    null_ptr_type);
template <class Fty>
  bool operator!= (null_ptr_type,
    const function <Fty>&);
template <class Fty>
  bool operator== (const function <Fty>&,
    null_ptr_type);
template <class Fty>
  bool operator== (null_ptr_type,
    const function <Fty>&);

    // ENHANCED BINDERS
template <class Fty, class T1, class T2, ..., class TN>
  unspecified bind (Fty, T1, T2, ..., TN);
template <class Ret,
  class Fty, class T1, class T2, ..., class TN>
  unspecified bind (Fty, T1, T2, ..., TN);
template <class Ret,
  class Ty, class T1, class T2, ..., class TN>
  unspecified bind (Ret Ty::*, T1, T2, ..., TN);

template <class Ty>
  struct is_bind_expression ;
template <class Ty>
  struct is_placeholder ;

    namespace placeholders {
extern unspecified _1 ; // _2, _3, ... _M
    }// namespace placeholders
  }  // namespace tr1
}  // namespace std


Section A.7. Header <memory> Synopsis

A.7. Header <memory> Synopsis

namespace std {
template <class Ty>
  class allocator ;
template <>
  class allocator<void> ;
template <class FwdIt, class Ty>
  class raw_storage_iterator ;
template <class Ty>
  class auto_ptr ;
template <class Ty>
  class auto_ptr_ref ;

    // TEMPLATE OPERATORS
template <class Ty>
  bool operator== (allocator <Ty>& left,
    allocator <Ty>& right);
template <class Ty>
  bool operator!= (allocator <Ty>& left,
    allocator <Ty>& right);

    // TEMPLATE FUNCTIONS
template <class Ty>
  pair <Ty *, ptrdiff_t>
    get_temporary_buffer (ptrdiff_t count);
template <class Ty>
  void return_temporary_buffer (Ty *pbuf);
template <class InIt, class FwdIt>
  FwdIt uninitialized_copy (InIt first, InIt last,
    FwdIt dest);
template <class FwdIt, class Ty>
  void uninitialized_fill (FwdIt first, FwdIt last,
    const Ty& val);
template <class FwdIt, class Size, class Ty>
  void uninitialized_fill_n (FwdIt first, Size count,
    const Ty& val);

  namespace tr1 {
    // TEMPLATE SHARED POINTERS
template <class Ty>
  class shared_ptr ;

template <class Ty1, class Ty2>
  bool operator== (const shared_ptr <Ty1>&,
    const shared_ptr <Ty2>&);
template <class Ty1, class Ty2>
  bool operator!= (const shared_ptr <Ty1>&,
    const shared_ptr <Ty2>&);
template <class Ty1, class Ty2>
  bool operator< (const shared_ptr <Ty1>&,
    const shared_ptr <Ty2>&);
template <class Elem, class Tr, class Ty>
  std :: basic_ostream <Elem, Tr>& operator<< (
    std :: basic_ostream <Elem, Tr>&, const shared_ptr <Ty>&);
template <class Ty>
  void swap (shared_ptr <Ty>&, shared_ptr <Ty>&);
template <class D, class Ty>
  D *get_deleter (const shared_ptr <Ty>&);

    // TEMPLATE WEAK POINTERS
template <class Ty>
  class weak_ptr ;

template <class Ty1, class Ty2>
  bool operator< (const weak_ptr <Ty1>&,
    const weak_ptr <Ty2>&);
template <class Ty>
  void swap (weak_ptr <Ty>&, weak_ptr <Ty>&);

    // UTILITY TEMPLATE CLASSES
template <class Ty>
  class enable_shared_from_this ;
class bad_weak_ptr ;

    // TEMPLATE FUNCTIONS
template <class Ty, class Other>
  shared_ptr <Ty> const_pointer_cast (
    const shared_ptr <Other>&);
template <class Ty, class Other>
  shared_ptr <Ty> dynamic_pointer_cast (
    const shared_ptr <Other>&);
template <class Ty, class Other>
  shared_ptr <Ty> static_pointer_cast (
    const shared_ptr <Other>&);
  } // namespace tr1
}  // namespace std


Section A.8. Header <utility> Synopsis

A.8. Header <utility> Synopsis

namespace std {
template <class T, class Ty2>
  struct pair ;

    // TEMPLATE FUNCTIONS
template <class Ty1, class Ty2>
  pair <Ty, Ty2> make_pair (Ty1 val1, Ty2 val2);
template <class Ty1, class Ty2>
  bool operator== (const pair <Ty, Ty2>& left,
    const pair <Ty1, Ty2>& right);
template <class Ty1, class Ty2>
  bool operator!= (const pair <Ty, Ty2>& left,
    const pair <Ty1, Ty2>& right);
template <class Ty1, class Ty2>
  bool operator< (const pair <Ty, Ty2>& left,
    const pair <Ty1, Ty2>& right);
template <class Ty1, class Ty2>
  bool operator> (const pair <Ty1, Ty2>& left,
    const pair <Ty1, Ty2>& right);
template <class Ty1, class Ty2>
  bool operator<= (const pair <Ty1, Ty2>& left,
    const pair <Ty1, Ty2>& right);
template <class Ty1, class Ty2>
  bool operator>= (const pair <Ty1, Ty2>& left,
    const pair <Ty1, Ty2>& right);

namespace rel_ops {
template <class Ty>
  bool operator!= (const Ty& left, const Ty& right);
template <class Ty>
  bool operator<= (const Ty& left, const Ty& right);
template <class Ty>
  bool operator> (const Ty& left, const Ty& right);
template <class Ty>
  bool operator>= (const Ty& left, const Ty& right);
}  // namespace rel ops

  namespace tr1 {
template <int Idx, class T1, class T2>
  RI& get (pair <T1, T2>& pr);
template <int Idx, class T1, class T2>
  const RI& get (const pair <T1, T2>& pr);

template <class T1, class T2>
  class tuple_element <0, pair <T1, T2>>;
template <class T1, class T2>
  class tuple_element <1, pair <T1, T2>>;

template <class T1, class T2>
  class tuple_size <pair <T1, T2>>;
  } // namespace tr1
}  // namespace std


Appendix B. Utility Headers

This appendix presents the contents of "sputil.h" (in Section B.1), the header used in the examples in Chapter 2; "mathutil.h" (in Section B.2), the header used in the examples in Chapter 12; and "rgxutil.h" (in Section B.3), the header used in the exercises in Chapter 15.


Section B.1. "sputil.h"

B.1. "sputil.h"

#ifndef SPUTIL_H
#define SPUTIL_H

#include <ostream>
#include <iostream>
#include <memory>

struct resource
  { // simple struct to demonstrate resource handling
  resource (int i0 = 0) : i(i0) {}
  int i;
  };

template <class Elem, class Tr>
std::basic_ostream<Elem, Tr>& operator<<(
  std::basic_ostream<Elem, Tr>& str,
  const resource& res)
  { // insert resource contents into stream
  return str << res.i;
  }

class d_res : public resource
  { // simple derived class
public:
  d_res (int i0) : resource (i0) {}
  };
static void show_rc(unsigned long count)
  { // show a reference count
  std::cout << " reference count: "
         << count << '\n';
  }

template <class Sp>
void show_refs (const std::tr1::shared_ptr<Sp>& sp)
  { // show reference count for shared ptr_objects
  show_rc (sp.use_count());
  }

template <class Sp>
void show_refs (const std::tr1::weak_ptr<Sp>& wp)
  { // show reference count for weak ptr_objects
  show_rc(wp.use_count());
  }

template <class Sp>
void show_refs(const Sp&)
  { // show reference count for other types (do nothing)
  }

template <class Sp>
void do_show(const Sp& sp)
  { // show contents of smart pointer
  std::cout << " pointer: "
         << (void*) sp.get() << '\n';
  if (sp.get())
    std::cout << " value: " << *sp << '\n';
  }

template <class Sp>
void show (const char *title, const Sp& sp)
  { // show title and contents of smart pointer
  std::cout << title << '\n';
  show_refs(sp);
  do_show(sp);
  }

template <class Ty>
void show (const char *title,
  const std::tr1::weak_ptr<Ty>& wp)
  { // show title and contents of weak_ptr object
  std::cout << title << '\n';
  if (wp.expired())
    std::cout << " expired \n";
  else
    { // show reference count before creating
      // temporary shared_ptr object
    show_rc(wp.use_count());
    do_show(wp.lock());
    }
  }

struct instrumented
  { // struct to report construction and destruction
  instrumented()
    { std::cout << " constructing instrumented\n"; }
  instrumented(const instrumented&)
    { std::cout << " copy constructing instrumented\n"; }
  instrumented& operator=(const instrumented&)
    { std::cout << " copying instrumented\n"; }
  ~ instrumented()
    { std::cout << " destroying instrumented\n"; }
  };
# endif   // SPUTIL H


Section B.2. "mathutil.h"

B.2. "mathutil.h"

#ifndef MATHUTIL_H
#define MATHUTIL_H

#include <fenv.h>
#include <iostream>

void show_exceptions(const char *title)
  { // show raised exceptions then clear all
  std::cout << title << "\n raised exceptions:";
  if (fetestexcept(FE_DIVBYZERO))
    std::cout << " divide-by-zero";
  if (fetestexcept(FE_INEXACT))
    std::cout << " inexact";
  if (fetestexcept(FE_INVALID))
    std::cout << " invalid";
  if (fetestexcept(FE_OVERFLOW))
    std::cout << " overflow";
  if (fetestexcept(FE_UNDERFLOW))
    std::cout << " underflow";
  std::cout << '\n';
  feclearexcept(FE_ALL_EXCEPT);
  }

# endif  // MATHUTIL_H


Section B.3. "rgxutil.h"

B.3. "rgxutil.h"

#ifndef RGXUTIL_H
#define RGXUTIL_H

#include <iostream>
#include <iomanip>
#include <regex>

static const char intro[] = "Trying to match `";
static const unsigned intro_chrs = sizeof(intro) - 1;

static const char *error(
  const std::tr1::regex_error& err)
  { // return description of error
  switch (err.code())
    { // select description
    case std::tr1::regex_constants::error_badbrace:
      return "invalid repeat count";
    case std::tr1::regex_constants::error_badrepeat:
      return "repeat not preceded by expression";
    case std::tr1::regex_constants::error_brace:
      return "unmatched curly brace";
    case std::tr1::regex_constants::error_brack:
      return "unmatched square bracket";
    case std::tr1::regex_constants::error_collate:
      return "invalid collating element name";
    case std::tr1::regex_constants::error_complexity:
      return "match too complex";
    case std::tr1::regex_constants::error_ctype:
      return "invalid character class name";
    case std::tr1::regex_constants::error_escape:
      return "invalid escape sequence";
    case std::tr1::regex_constants::error_paren:
      return "unmatched parenthesis";
    case std::tr1::regex_constants::error_range:
      return "invalid character range specifier";
    case std::tr1::regex_constants::error_space:
      return "out of resources";
      case std::tr1::regex_constants::error_stack:
      return "out of memory";
    case std::tr1::regex_constants::error_backref:
      return "invalid back reference";
    default:
      return "unknown error";;
    }
  }

static void do_match(const char *str, const char *tgt,
  std::tr1::regex_constants::syntax_option_type flags)
  {
  std::tr1::regex rgx;
  std::cout << "Regular expression `" << str << "`: ";
  try
    { // compile regular expression
    rgx.assign(str, flags);
    std::cout << "okay \n";
    }
  catch(const std::tr1::regex_error& err)
    { // report regular expression error
    std::cout << "invalid \n " << error(err) << '\n';
    return;
    }
  if (tgt)
    { // check for match
    std::tr1::cmatch mr;
    std::cout << intro << tgt << "`, ";
    try
      { // try to match
      if (std::tr1::regex_match(tgt, mr, rgx))
          { // report successful match
          std::cout << "success\n";
          for (int i = 0; i < mr.size(); ++ i)
            std::cout << std::setw(intro_chrs - 2)
             << i << ':'
             << std::setw(mr.position(i) + 1) << ' '
             << mr[i] << '\n';
          }
      else
        std::cout << "no match\n";
      }
    catch(const std::tr1::regex_error& err)
      { // report match error
      std::cout << "match failed \n "
             << error(err) << '\n' ;
      }
    }
  }

static void match_ECMA(
  const char *str, const char *tgt = 0)
  {
  do_match(str, tgt,
    std::tr1::regex_constants::ECMAScript);
  }

static void match_grep(
  const char * str, const char * tgt = 0)
  {
  do_match(str, tgt,
    std::tr1::regex_constants::grep);
  }

static void match_ere(
  const char *str, const char *tgt = 0)
  {
  do_match(str, tgt,
    std::tr1::regex_constants::extended);
  }

# endif // RGXUTIL_H


Appendix C. Multithreading

Neither the C++ standard nor the Library Technical Report says much about multithreaded applications, in part because most programs do not need to be multithreaded, and most programmers should not be writing multithreaded code. For those uncommon cases in which multithreading is appropriate, however, it's important to understand what you need to do to use the standard C++ library and the TR1 library components safely in a multithreaded application (Section C.1). Remember, though, that none of this is required by either the C++ standard or the Library Technical Report but instead reflects the general concensus on how to design libraries for use in multithreaded applications (Section C.2). Always check your library's documentation.


Section C.1. Problems

C.1. Problems

When writing a multithreaded application, you have to think about two problems: avoiding conflicting changes to shared data and making sure that changes to shared data are visible to other threads. Most programmers are familiar with the first of these; the second is becoming more important as we move to hardware systems with multiple CPUs.

If two threads are changing the same data object at the same time, the result will likely be a nonviable hybrid, with some parts from one thread and other parts from the other thread. To prevent this from happening, you have to make sure that all the changes made by one thread have been written to the data object before the other thread makes any changes. You do this by locking a mutex object; when a thread tries to lock a mutex object that is already locked, the execution of that thread is suspended until the thread that locked the mutex object unlocks it. This serializes access to the shared data object, giving each of the threads a coherent view of the contents of the object.

In a hardware system with multiple CPUs, all of them usually share most or all of the system's main memory, and each CPU has its own private cache memory. Each CPU reads data from and writes data to its cache; this speeds up the CPU's work because the CPU doesn't have to contend with other CPUs for access to main memory. However, because the CPU is working with its cache instead of main memory, it might not see changes that other CPUs have made to the contents of main memory, and changes made by it might not have made it out to main memory, so won't be seen by other CPUs. So from time to time, each CPU has to synchronize the data in its cache with the corresponding data in main memory: Any data that has been written to the cache has to be flushed to main memory, and any data that another CPU has changed in main memory has to be refreshed in the cache.

On most systems, changes made to a shared object before creation of a thread are visible to code in that thread. At the other end, when a thread terminates, any changes made to a shared object by that thread are visible to any thread that checks the status of the terminated threadby, for example, calling pthread_join on POSIX systems. In between, after a thread unlocks a mutex, all changes to global data made by that thread are visible to any other thread that subsequently locks the mutex:

int g1 =  0;
int g2 =  0;

// thread 1                        // thread 2
g1 = 1;                            // ...
start_thread2 ();                  assert (g1 == 1);     // 1
lock_mutex ();                     lock_mutex ();
unlock_mutex ();                   g1 =  2;
assert (g1 == 2);     // 2         unlock_mutex ();
wait_for_thread2 ();               g2 =  3;
assert (g2 == 3);     // 3         exit_thread ();

In the preceding code, assert number 1 will always succeed. The change made to g1 by thread 1 is visible to thread 2 because thread 1 created thread 2 after it changed g1. Also, assert number 3 will always succeed. Thread 2 set the value of g2 to 3 before it terminated, and thread 1 waited until thread 2 terminated before taking its final look at the value of g2.

The second assert is more complicated. If thread 2 locked the mutex before thread 1 did, the assert will succeed. In that case, thread 2 made the change before unlocking the mutex, so the change will be visible to threads that subsequently lock the mutex. On the other hand, if thread 1 locked the mutex before thread 2 did, there's no way to know what will happen. There is no guarantee that the change made by thread 2 will be visible, but there is also no guarantee that it won't. So thread 1 could see either 1 or 2 in g1. But it's worse than that: It's possible that a thread switch could occur while thread 2 is writing the new value to g1, creating a nonviable hybrid. This is a race condition: The validity and the result of the code depend, in unpredictable ways, on the timing of the execution of the code in the two threads.


Section C.2. Libraries and Multithreading

C.2. Libraries and Multithreading

If you think about it, it should become clear that a library cannot solve these multithreading problems. Ensuring that accesses to shared data are properly synchronized requires that an application be designed with thread safety in mind. For example:

void show ()
  {
  std :: cout << " hello, " << " world \n";
  }

The two insertion operations are separate functions. The implementation of the stream inserter can protect cout's internal data from conflicting writes, but if show is called from multiple threads, there is nothing the implementation can reasonably do to prevent a thread switch between the two insertions. The output of such a program could have multiple hellos and multiple worlds instead of the orderly sequence of lines that the programmer might have expected. To maintain the proper order, the application must guard all stream insertions:

void show ()
  {
  mutex lock ; // constructor locks, destructor unlocks
  std :: cout << " hello, " << " world \n";
  }

However, library writers should avoid making things more difficult for application designers concerned with writing fast and robust multithreaded applications. As we saw earlier, applying visibility rules requires knowing when the contents of a shared data object have been changed. A good library implementation will change the contents of a shared data object only when a program explicitly changes that object.

That may seem obvious, but sneak paths often modify objects behind the scenes. For example, at one time or another, you've probably written code to count the number of objects of a particular type that are in existence: You add a static data member to hold the count, and then each constructor increments the count, and each destructor decrements it. This seems innocuous, but if you create two of these objects in two separate threads, you may find that neither one has the correct count; the static counter is shared data, and without synchronization, there is no guarantee that changes made by either thread will be visible to the other.[1]

[1] This problem is also discussed in Chapter 2.

Most library implementations make the following promises.

  • Multiple threads can read data from the same object without interference

  • Changes to one object do not affect other objects of the same type.

Keeping these promises in mind, you can write robust multithreaded applications by applying the visibility and locking rules that we just talked about. Using objects from the standard C++ library and the TR1 library won't introduce additional problems.


Bibliography

[AG05] David Abrahams and Aleksey Gurtovoy. C++ Template Metaprogramming: Concepts, Tools, and Techniques from Boost and Beyond. Boston: Addison-Wesley, 2005.

[Ale01] Andrei Alexandrescu. Modern C++ Design: Generic Programming and Design Patterns Applied. Boston: Addison-Wesley, 2001.

[Aus99] Matthew H. Austern. Generic Programming and the STL: Using and Extending the C++ Standard Template Library. Reading, Massachusetts: Addison-Wesley, 1999.

[Bec00a] Pete Becker. Floating-point basics. C/C++ Users Journal, June, 2000. Available at www.petebecker.com/js200006.html.

[Bec00b] Pete Becker. Errors in floating-point calculations. C/C++ Users Journal, July, 2000. Available at www.petebecker.com/js200007.html.

[Bec00c] Pete Becker When bad things happen to good numbers. C/C++ Users Journal, October, 2000. Available at www.petebecker.com/js200010.html.

[Bec00d] Pete Becker. Trap handlers, sticky bits, and floating-point comparisons. C/C++ Users Journal, December, 2000. Available at www.petebecker.com/js200012.html.

[CLR90] Thomas H. Cormen, Charles E. Leiserson, and Ronald L. Rivest. Introduction to Algorithms. McGraw-Hill, 1990.

[Ecm03] Ecma International, Geneva. Ecma-262, ECMAScript Language Specification, 3rd ed., December 2003.

[Fri02] Jeffrey Friedl. Mastering Regular Expressions, 2nd ed. O'Reilly, 2002.

[Gol91] David Goldberg. What every computer scientist should know about floating-point arithmetic. Computing Surveys, March, 1991. Available at http://docs.sun.com/source/806-3568/ncg_goldberg.html.

[Int89] International Electrotechnical Commission, Geneva. IEC Standard 60559:19898, Binary Floating-point Arithmetic for Microprocessor Systems, 1989.

[Int90] International Standards Organization, Geneva. ISO/IEC Standard 9899:1990, Programming LanguagesC, 1990.

[Int92] International Standards Organization, Geneva. ISO Standard 31-11, Quantities and UnitsPart 11: Mathematical signs and symbols for use in the physical sciences and technology, 1992.

[Int95] International Standards Organization, Geneva. Amendment 1 to ISO/IEC Standard 9899:1990, Programming LanguagesC, 1995.

[Int99] International Standards Organization, Geneva. ISO/IEC Standard 9899:1999, Programming LanguagesC, 1999.

[Int03a] International Standards Organization, Geneva. ISO/IEC Standard 14882:2003, Programming LanguagesC++, 2003.

[Int03b] International Standards Organization, Geneva. ISO/IEC Standard 9945-1:2003, Information TechnologyPortable Operating System Interface (POSIX)Part 1: Base Definitions, 2003.

[Int03c] International Standards Organization, Geneva. ISO/IEC Standard 9945-1:2003, Information TechnologyPortable Operating System Interface (POSIX)Part 3: Shell and Utilities, 2003.

[Jos99] Nicolai M. Josuttis. The C++ Standard Library: A Tutorial and Reference. Reading, Massachusetts: Addison-Wesley, 1999.

[Knu97] Donald E. Knuth. The Art of Computer Programming, Volume 1: Fundamental Algorithms, 3rd ed. Reading, Mass.: Addison-Wesley, 1997.

[Knu98a] Donald E. Knuth. The Art of Computer Programming, Volume 2: Seminumerical Algorithms, 3rd ed. Reading, Mass.: Addison-Wesley, 1998.

[Knu98b] Donald E. Knuth. The Art of Computer Programming, Volume 3: Sorting and Searching, 2nd ed. Reading, Mass.: Addison-Wesley, 1998.

[NIS] NIST/SEMATECH. e-Handbook of Statistical Methods. Available at www.itl.nist.gov/div898/handbook.

[PTVF92] William H. Press, Saul A. Teukolsky, William T. Vetterling, and Brian P. Flannery. Numerical Recipes in C, 2nd ed. Cambridge: Cambridge University Press, 1992.

[VJ03] David Vandevoorde and Nicolai M. Josuttis. C++ Templates: The Complete Guide. Boston: Addison-Wesley, 2003.


Index

[SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [L] [M] [N] [O] [P] [R] [S] [T] [U] [V] [W] [X] [Z]


SYMBOL

Index

[SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [L] [M] [N] [O] [P] [R] [S] [T] [U] [V] [W] [X] [Z]

<array> header
<ccomplex> header
<cctype> header
<cfenv> header
<cfloat> header
<cinttypes> header 2nd 3rd
<cmath> header
<complex.h> header 2nd
<cstdbool> header
<cstdint> header
<cwctype> header
<fenv.h> header 2nd
<float.h> header 2nd
<functional> header 2nd 3rd 4th 5th 6th 7th 8th 9th
<inttypes.h> header 2nd
<ios> header
<math.h> header 2nd 3rd 4th
<memory> header 2nd
<random> header
<regex> header 2nd 3rd 4th 5th 6th 7th
<stdbool.h> header
<stdint.h> header 2nd
<tgmath.h> header
<tuple> header
<typetraits> header
<unordered_map> header
<unordered_set> header
<utility> header
__bool_true_false_are_defined
_Bool


A

Index

[SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [L] [M] [N] [O] [P] [R] [S] [T] [U] [V] [W] [X] [Z]

abs 2nd 3rd 4th 5th 6th
abstract class
acos 2nd
acosh 2nd
algorithm
alignment
anchor
arg
arithmetic type
array
assign
at
back
begin
class array
const_iterator
const_pointer
const_reference
const_reverse_iterator
data
difference_type
empty
end
front
get 2nd
iterator
max_size
operator!= 2nd
operator< 2nd
operator<= 2nd
operator== 2nd
operator> 2nd
operator>= 2nd
operator[]
pointer
rbegin
reference
rend
reverse_iterator
size
size_type
swap 2nd
tuple_element 2nd
tuple_size 2nd
value_type
asin
asin
asinh 2nd
assign control
assoc_laguerre
assoc_legendre
associative container
atan 2nd
atan2
atanh 2nd
auto_ptr


B

Index

[SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [L] [M] [N] [O] [P] [R] [S] [T] [U] [V] [W] [X] [Z]

back reference
bad_function_call
bad_weak_ptr
basic_regex 2nd
bernoulli_distribution
beta
BinaryTypeTrait
bind 2nd
_1
additional arguments
bind arguments
extending
is_bind_expression 2nd
is_placeholder 2nd
ordinary arguments
placeholders 2nd
reference_wrapper 2nd
binomial_distribution
bitmask type
Boolean types
Boost
bound arguments
bracket expression


C

Index

[SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [L] [M] [N] [O] [P] [R] [S] [T] [U] [V] [W] [X] [Z]

C-style array
cabs
cacos
cacosh
call wrapper 2nd 3rd 4th
in general
call wrapper type
callable object 2nd
callable type 2nd
capture group
carg
case-insensitive matching
casin
casinh
catan
catanh
cbrt
cconj
ccos
ccosh
ceil
cexp
character class
character classification
character range
Checkpointing
cimag
clog
cmatch
collating element
collating symbol
comp_ellint_1
comp_ellint_2
comp_ellint_3
comparison operators
composite
compound engine
compound type
compromise rule
concatenated regular expression
conf_hyperg
conformance
conforming implementation
const_pointer_cast
container 2nd
comparisons
nested types
operations
continuous distribution 2nd
control escape sequence
controlled resource
controlled sequence
controls
copysign
cos 2nd
cosh 2nd
cpow
cproj
creal
cref 2nd
cregex_iterator
cregex_token_iterator
csin
csinh
csqrt
csub_match
ctan
ctanh
current match
cycle
cyl_bessel_i
cyl_bessel_j
cyl_bessel_k
cyl_neumann


D

Index

[SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [L] [M] [N] [O] [P] [R] [S] [T] [U] [V] [W] [X] [Z]

deleter object
denormal
denormalized
diagnosable rule
diagnostic message
Dinkumware, Ltd.
discard_block
discrete distribution 2nd
div 2nd 3rd 4th
domain error
dsw character escape
dynamic_pointer_cast


E

Index

[SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [L] [M] [N] [O] [P] [R] [S] [T] [U] [V] [W] [X] [Z]

element
ellint_1
ellint_2
ellint_3
empty function object
empty regular expression
empty shared_ptr
empty weak_ptr
enable_shared_from_this
enumeration type
equality comparison 2nd
equivalence class
erf
erfc
error_type
examples, about
exp 2nd
exp2
expint
expired
expm1
exponent
exponential_distribution


F

Index

[SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [L] [M] [N] [O] [P] [R] [S] [T] [U] [V] [W] [X] [Z]

fabs 2nd
false_type
fdim
FE_ALL_EXCEPT
FE_DFL_ENV
FE_DIVBYZERO
FE_DOWNWARD
FE_INEXACT
FE_INVALID
FE_OVERFLOW
FE_TONEAREST
FE_TOWARDZERO
FE_UNDERFLOW
FE_UPWARD
feclearexcept
fegetenv
fegetexceptflag
fegetround
feholdexcept
fenv_t
feraiseexcept
fesetenv
fesetexceptflag
fesetround
fetestexcept
feupdateenv
fexcept_t
file format escape
fixed width integer types
exact width
fastest
macros
minimum width
pointers
widest
floating-point control mode
floating-point environment
floating-point exception
floating-point status flag
floating-point type
floating-point types
model
properties
value ranges
floor
fma
fmax
fmin
fmod
formal language, use of
forwarding call wrapper
forwarding problem
FP_FAST_FMA
FP_ILOGB0
FP_ILOGBNAN
FP_INFINITE
FP_NAN
FP_NORMAL
FP_SUBNORMAL
FP_ZERO
fpclassify
frexp
function 2nd
construction
conversion to Boolean type
derived from binary_function
derived from unary_function
function::operator()
function::operator=
function::result_type
function::swap
function::target
function::target_type
operator!=
operator==
function type
fundamental type


G

Index

[SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [L] [M] [N] [O] [P] [R] [S] [T] [U] [V] [W] [X] [Z]

gamma_distribution
geometric_distribution
get 2nd 3rd 4th
greedy repetition


H

Index

[SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [L] [M] [N] [O] [P] [R] [S] [T] [U] [V] [W] [X] [Z]

has a deleter
hash table
hermite
hexadecimal escape sequence
hexfloat
HUGE_VAL
hyperg
hypot


I

Index

[SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [L] [M] [N] [O] [P] [R] [S] [T] [U] [V] [W] [X] [Z]

I/O
hexadecimal
identity escape
ill-formed program
ilogb
imag
imaxabs 2nd
imaxdiv 2nd
imaxdiv_t 2nd
implementation-defined behavior
individual character
infinity
input sequence
insert iterator
int16_t
int32_t
int64_t
int8_t
int_fast16_t
int_fast32_t
int_fast64_t
int_fast8_t
INT_FAST N _MAX macros
INT_FAST N _MIN macros
int_least16_t
int_least32_t
int_least64_t
int_least8_t
INT_LEAST N _MAX macros
INT_LEAST N _MIN macros
integer types
integral type
integral_constant
INTMAX_MAX
INTMAX_MIN
intmax_t
INT N _C macros
INT N _MAX macros
INT N _MIN macros
INTPTR_MAX
INTPTR_MIN
intptr_t
INVOKE
INVOKE_R
is_bind_expression 2nd
is_placeholder 2nd
isblank
isfinite
isgreater
isgreaterequal
isinf
isless
islessequal
islessgreater
isnan
isnormal
isunordered
iswblank
iterator


L

Index

[SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [L] [M] [N] [O] [P] [R] [S] [T] [U] [V] [W] [X] [Z]

laguerre
ldexp
legendre
lexicographical comparison
lgamma
linear_congruential
llabs 2nd
lldiv 2nd
lldiv_t 2nd
llrint
llround
load factor
locale-sensitive match
locale-sensitive ranges
log 2nd
log10
log1p
log2
logb
lrint
lround


M

Index

[SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [L] [M] [N] [O] [P] [R] [S] [T] [U] [V] [W] [X] [Z]

make_tuple 2nd
match_flag_type 2nd
match_results
match_results::format 2nd
MATH_ERREXCEPT
math_errhandling
MATH_ERRNO
"mathutil.h" header 2nd
mem_fn 2nd
binding to object
pointer to member data
result_type
member pointer
mersenne_twister
minstd_rand
minstd_rand0
modf
mt19937
multiple CPUs
multithreading 2nd
libraries and
problems 2nd
mutex


N

Index

[SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [L] [M] [N] [O] [P] [R] [S] [T] [U] [V] [W] [X] [Z]

NaN 2nd
nan
nearbyint
negative assert
negative word boundary assert
nextafter
nexttoward
non-normative
noncapture group
nongreedy repetition
normal_distribution
normalized
normative


O

Index

[SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [L] [M] [N] [O] [P] [R] [S] [T] [U] [V] [W] [X] [Z]

object type
octal escape sequence
One Definition Rule
operand
operand sequence
order comparison 2nd
ordinary character
original owner
original pointer
output sequence
overload
owns


P

Index

[SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [L] [M] [N] [O] [P] [R] [S] [T] [U] [V] [W] [X] [Z]

pair 2nd
get
tuple_element
tuple_size
Parallelizing a calculation
points to
poisson_distribution
polymorphic type
positive assert
pow 2nd
predefined engines
printf
PRIxxx macros
PTRDIFF_MAX
PTRDIFF_MIN


R

Index

[SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [L] [M] [N] [O] [P] [R] [S] [T] [U] [V] [W] [X] [Z]

race condition
raise
random number distribution
random number distributions
bernoulli_distribution
binomial_distribution
continuous
discrete
exponential_distribution
gamma_distribution
geometric_distribution
normal_distribution
poisson_distribution
uniform_int
uniform_real
random number engine
random number engines
discard_block
linear_congruential
mersenne_twister
minstd_rand
minstd_rand0
mt19937
random_device
ranlux3
ranlux3_01
ranlux4
ranlux4_01
ranlux64_base_01
ranlux_base_01
subtract_with_carry
subtract_with_carry_01
xor_combine
random number generator
random numbers
engine templates
predefined engines
variate_generator
random_device
range
range error
ranlux3
ranlux3_01
ranlux4
ranlux4_01
ranlux64_base_01
ranlux_base_01
reachable
real
ref 2nd
reference count 2nd
reference_wrapper 2nd
construction
operator()
result_type
type
regex_constants
regex_error
regex_iterator
regex_match
regex_replace
regex_search
regex_token_iterator
regex_traits 2nd
regular expression
regular expression grammar
regular expression searches
cmatch
cregex_iterator
cregex_token_iterator
csub_match
empty matches
lost anchors
lost word boundaries
match_flag_type
match_results
match_results::format
optimizing
regex_iterator
regex_match
regex_search
regex_token_iterator
smatch
sregex_iterator
sregex_token_iterator
ssub_match
storing results
sub_match
wcmatch
wcregex_iterator
wcregex_token_iterator
wcsub_match
wsmatch
wsregex_iterator
wsregex_token_iterator
wssub_match
regular expression traits class
regular expressions
basic_regex 2nd
case-insensitive comparison 2nd
character ranges
customizing
error_type
errors
formatting with
escape sequences
grammars
ignoring submatches
match_flag_type
match_results::format
overview
regex_constants
regex_error
regex_replace
regex_traits 2nd
syntax_option_type
rehashing
releases control
remainder
remquo
repetition count
resource limits
result_of
reversible container
"rgxutil.h" header 2nd
riemann_zeta
rint
round
rounding mode


S

Index

[SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [L] [M] [N] [O] [P] [R] [S] [T] [U] [V] [W] [X] [Z]

scalar type
scalbln
scalbn
scanf
SCNxxx macros
sequence
sequence container
serialization
shared data, changes to 2nd 3rd
shared pointer conversions
shared_ptr
const_pointer_cast
constructing 2nd 3rd 4th
destroying
dynamic_pointer_cast
empty
get
get_deleter
operator boolean-type
operator!=
operator*
operator->
operator<
operator<<
operator=
operator=
operator==
overview
quirks
reset
static_pointer_cast
swap
unique
use_count
SIG_ATOMIC_MAX
SIG_ATOMIC_MIN
signbit
significand
simple call wrapper
simple engine
sin 2nd
sinh 2nd
SIZE_MAX
smart pointers
bad_weak_ptr
definitions of terms
destruction of controlled resources
shared_ptr [See shared_ptr.]
weak_ptr [See weak_ptr.]
smatch
sph_bessel
sph_legendre
sph_neumann
"sputil.h" header 2nd
sqrt 2nd
sregex_iterator
sregex_token_iterator
ssub_match
Standard Template Library
standards
C 2nd
C++
IEC 60559
state
static_pointer_cast
strftime
strtod
strtof
strtoimax 2nd
strtol
strtold
strtoll
strtoul
strtoull
strtoumax 2nd
sub_match
subexpression
subtract_with_carry
subtract_with_carry_01
suffix iterator
syntax_option_type


T

Index

[SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [L] [M] [N] [O] [P] [R] [S] [T] [U] [V] [W] [X] [Z]

tan 2nd
tanh 2nd
target load factor
target object 2nd
text representation
text-conversion functions
tgamma
threads [See multithreading.]
tie
TransformationTypeTrait
trap handler
trivial copy assignment operator
trivial copy constructor
trivial default constructor
trivial destructor
true_type
trunc
tuple
comparing
constructing
get 2nd
maketuple
operator=
references
tie
tuple_element
tuple_size
tuple_element 2nd 3rd 4th
tuple_size 2nd 3rd 4th
tuples
type predicate
type query
type traits
alignment
BinaryTypeTrait
composite type categories
compromise rule
false_type
helper types
integral_constant
primary type categories
TransformationTypeTrait
true_type
type properties
type relationships
type transformations
UnaryTypeTrait
type transformation


U

Index

[SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [L] [M] [N] [O] [P] [R] [S] [T] [U] [V] [W] [X] [Z]

uint16_t
uint32_t
uint64_t
uint8_t
uint_fast16_t
uint_fast32_t
uint_fast64_t
uint_fast8_t
UINT_FAST N _MAX macros
uint_least16_t
uint_least32_t
uint_least64_t
uint_least8_t
UINT_LEAST N _MAX macros
UINTMAX_MAX
uintmax_t
UINT N _C macros
UINT N _MAX macros
UINTPTR_MAX
uintptr_t
UnaryTypeTrait
undefined behavior
Unicode escape sequence
uniform_int
uniform_real
unordered
unordered associative container 2nd
in general
nested types
operations
rehash
tuning
unordered_map
unordered_multimap
unordered_multiset
unordered_set
unspecified behavior


V

Index

[SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [L] [M] [N] [O] [P] [R] [S] [T] [U] [V] [W] [X] [Z]

va_copy macro
variable-length argument lists 2nd
variate_generator


W

Index

[SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [L] [M] [N] [O] [P] [R] [S] [T] [U] [V] [W] [X] [Z]

WCHAR_MAX
WCHAR_MIN
wcmatch
wcregex_iterator
wcregex_token_iterator
wcstod
wcstof
wcstoimax 2nd
wcstol
wcstold
wcstoll
wcstoul
wcstoull
wcstoumax 2nd
wcsub_match
weak result type
weak_ptr
constructing 2nd
destroying
empty
expired
lock
operator<
operator=
overview
reset
swap
use_count
well-formed program
wildcard character
WINT_MAX
WINT_MIN
word boundary
word boundary assert
word characters
wsmatch
wsregex_iterator
wsregex_token_iterator
wssub_match


X

Index

[SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [L] [M] [N] [O] [P] [R] [S] [T] [U] [V] [W] [X] [Z]

xor_combine


Z

Index

[SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [L] [M] [N] [O] [P] [R] [S] [T] [U] [V] [W] [X] [Z]

zero-length match